diff --git a/src/PrivateAnalyzer/private_arrays_search.cpp b/src/PrivateAnalyzer/private_arrays_search.cpp index f173575..7ee76aa 100644 --- a/src/PrivateAnalyzer/private_arrays_search.cpp +++ b/src/PrivateAnalyzer/private_arrays_search.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -16,6 +17,8 @@ using namespace std; +static unordered_set collapsed; + static void RemoveEmptyPoints(ArrayAccessingIndexes& container) { ArrayAccessingIndexes resultContainer; @@ -49,43 +52,81 @@ static void Collapse(Region* region) if (region->getBasickBlocks().empty()) return; - for (auto& [arrayName, arrayRanges] : region->getHeader()->array_out) + bool firstRegion = true; + for (Region* basickBlock : region->getBasickBlocks()) { - for (Region* byBlock : region->getBasickBlocks()) + if (basickBlock->getNextRegions().empty()) { - AccessingSet intersection = byBlock->array_def[arrayName].Intersect(arrayRanges); - region->array_def[arrayName] = region->array_def[arrayName].Union(intersection); + if (firstRegion) + { + region->array_def = basickBlock->array_out; + firstRegion = false; + } + else + { + unordered_set toErease; + for (auto& [arrayName, arrayRanges] : region->array_def) + { + if (basickBlock->array_out.find(arrayName) != basickBlock->array_out.end()) + arrayRanges = arrayRanges.Intersect(basickBlock->array_out[arrayName]); + else + { + arrayRanges = AccessingSet(); + toErease.insert(arrayName); + } + } + for (string arrayName : toErease) + region->array_def.erase(arrayName); + } } } - for (auto& byBlock : region->getBasickBlocks()) + RegionInstruction instruction; + instruction.def = move(region->array_def); + + + for (auto& byBlock : region->getBasickBlocks()) { - for (auto& [arrayName, arrayRanges] : byBlock->array_use) + for (auto& instruction : byBlock->instructions) { - AccessingSet diff = byBlock->array_use[arrayName].Diff(byBlock->array_in[arrayName]); - region->array_use[arrayName] = region->array_use[arrayName].Union(diff); + for (auto& [arrayName, _] : instruction.use) + { + AccessingSet diff = instruction.use[arrayName].Diff(instruction.in[arrayName]); + region->array_use[arrayName] = region->array_use[arrayName].Union(diff); + } } } ArrayAccessingIndexes useUnionB; for (auto& byBlock : region->getBasickBlocks()) - for (auto& [arrayName, _] : byBlock->array_use) - useUnionB[arrayName] = useUnionB[arrayName].Union(byBlock->array_use[arrayName]); + for (auto& instruction : byBlock->instructions) + for (auto& [arrayName, _] : instruction.use) + useUnionB[arrayName] = useUnionB[arrayName].Union(instruction.use[arrayName]); for (auto& [arrayName, _] : useUnionB) region->array_priv[arrayName] = useUnionB[arrayName].Diff(region->array_use[arrayName]); + instruction.use = move(region->array_use); - for (Region* prevBlock : region->getHeader()->getPrevRegions()) + for (Region* prevBlock : region->getHeader()->getPrevRegions()) + { prevBlock->replaceInNextRegions(region, region->getHeader()); + region->addPrevRegion(prevBlock); + } for (Region* nextBlock : region->getHeader()->getNextRegions()) + { nextBlock->replaceInPrevRegions(region, region->getHeader()); + region->addNextRegion(nextBlock); + } + region->instructions.push_back(instruction); + } static void SolveDataFlowIteratively(Region* DFG) { - unordered_set worklist(DFG->getBasickBlocks()); + auto blocks = DFG->getBasickBlocks(); + std::unordered_set worklist(blocks.begin(), blocks.end()); do { Region* b = *worklist.begin(); @@ -103,7 +144,7 @@ static void SolveDataFlowIteratively(Region* DFG) if (prevBlock->array_out.empty()) { newIn.clear(); - continue; + break; } for (const auto& [arrayName, accessSet] : prevBlock->array_out) @@ -143,17 +184,150 @@ static void SolveDataFlowIteratively(Region* DFG) while (!worklist.empty()); } +static void SolveForBasickBlock(Region* block) +{ + ArrayAccessingIndexes newIn; + bool flagFirst = true; + for (Region* prevBlock : block->getPrevRegions()) + { + if (flagFirst) + { + newIn = prevBlock->array_out; + flagFirst = false; + } + else + { + if (prevBlock->array_out.empty()) + { + newIn.clear(); + break; + } + + for (const auto& [arrayName, accessSet] : prevBlock->array_out) + { + if (newIn.find(arrayName) != newIn.end()) + newIn[arrayName] = newIn[arrayName].Intersect(accessSet); + else + newIn[arrayName] = AccessingSet(); + } + } + } + + if (block->instructions.empty()) + block->instructions.push_back(RegionInstruction()); + + block->instructions[0].in = move(newIn); + + for (int i = 0; i < block->instructions.size(); i++) + { + auto& instruction = block->instructions[i]; + + if (i > 0) + instruction.in = block->instructions[i - 1].out; + + ArrayAccessingIndexes newOut; + if (instruction.def.empty()) + newOut = instruction.in; + else if (instruction.in.empty()) + newOut = instruction.def; + else + { + for (auto& [arrayName, accessSet] : instruction.def) + { + if (instruction.in.find(arrayName) != instruction.in.end()) + newOut[arrayName] = instruction.def[arrayName].Union(instruction.in[arrayName]); + else + newOut[arrayName] = accessSet; + } + for (auto& [arrayName, accessSet] : instruction.in) + { + if (newOut.find(arrayName) == newOut.end()) + { + newOut[arrayName] = accessSet; + } + } + } + + instruction.out = move(newOut); + } + if (!block->instructions.empty()) + block->array_out = block->instructions.back().out; +} + +static void SolveDataFlowTopologically(Region* DFG) +{ + for (Region* b : DFG->getBasickBlocks()) + { + collapsed.insert(b); + SolveForBasickBlock(b); + } +} + static void SolveDataFlow(Region* DFG) { if (!DFG) return; - - SolveDataFlowIteratively(DFG); for (Region* subRegion : DFG->getSubRegions()) + { SolveDataFlow(subRegion); + DFG->addBasickBlocks(subRegion); + } + vector& blocks = DFG->getBasickBlocks(); + auto pos = remove_if(blocks.begin(), blocks.end(), [](Region* r) { return collapsed.find(r) != collapsed.end(); }); + blocks.erase(pos, blocks.end()); + TopologySort(DFG->getBasickBlocks(), DFG->getHeader()); + SolveDataFlowTopologically(DFG); Collapse(DFG); } +static bool getArrayDeclaredDimensions(SgArrayRefExp* arrayRef, vector& declaredDims) +{ + declaredDims.clear(); + if (!arrayRef || !arrayRef->symbol() || !isSgArrayType(arrayRef->symbol()->type())) + return false; + SgArrayType* arrayType = (SgArrayType*)arrayRef->symbol()->type(); + int dimCount = arrayType->dimension(); + for (int i = 0; i < dimCount; i++) + { + SgExpression* sizeExpr = arrayType->sizeInDim(i); + SgConstantSymb* constValSymb = isSgConstantSymb(sizeExpr->symbol()); + string strDimLength; + if (sizeExpr && sizeExpr->variant() == INT_VAL) + strDimLength = sizeExpr->unparse(); + else if (constValSymb) + strDimLength = constValSymb->constantValue()->unparse(); + else + return false; + + if (strDimLength == "0") + return false; + declaredDims.push_back((uint64_t)stoi(strDimLength)); + } + return true; +} + +static bool CheckDimensionLength(const AccessingSet& array) +{ + if (array.GetElements().empty()) + return false; + size_t dimCount = array.GetElements()[0].size(); + SgArrayRefExp* arrayRef = array.GetElements()[0][0].array; + if (!arrayRef) + return false; + vector declaredDims(dimCount); + if (!getArrayDeclaredDimensions(arrayRef, declaredDims)) + return false; + vector testArray(dimCount); + for (size_t i = 0; i < dimCount; i++) + { + testArray[i] = { 1, 1, declaredDims[i], nullptr }; + } + AccessingSet diff = AccessingSet({ testArray }).Diff(array); + + return diff.GetElements().empty(); +} + + static void AddPrivateArraysToLoop(LoopGraph* loop, const ArrayAccessingIndexes& privates, set& insertedPrivates) { SgStatement* spfStat = new SgStatement(SPF_ANALYSIS_DIR); @@ -163,6 +337,8 @@ static void AddPrivateArraysToLoop(LoopGraph* loop, const ArrayAccessingIndexes& set arraysToInsert; for (const auto& [_, accessingSet] : privates) { + if (!CheckDimensionLength(accessingSet)) + continue; for (const auto& arrayElement : accessingSet.GetElements()) { if (arrayElement.empty()) @@ -190,11 +366,11 @@ static void AddPrivateArraysToLoop(LoopGraph* loop, const ArrayAccessingIndexes& toAdd->setLhs(new SgVarRefExp(elem)); } - if (arraysToInsert.size() == 0) - printInternalError(convertFileName(__FILE__).c_str(), __LINE__); - - loop->loop->insertStmtBefore(*spfStat, *loop->loop->controlParent()); - insertedPrivates.insert(spfStat); + if (arraysToInsert.size() != 0) + { + loop->loop->insertStmtBefore(*spfStat, *loop->loop->controlParent()); + insertedPrivates.insert(spfStat); + } } void FindPrivateArrays(map> &loopGraph, map>& FullIR, set &insertedPrivates) diff --git a/src/PrivateAnalyzer/range_structures.cpp b/src/PrivateAnalyzer/range_structures.cpp index 373ffa5..e813c01 100644 --- a/src/PrivateAnalyzer/range_structures.cpp +++ b/src/PrivateAnalyzer/range_structures.cpp @@ -132,8 +132,10 @@ static vector ElementsIntersection(const vector& static vector> ElementsDifference(const vector& firstElement, const vector& secondElement) { - if (firstElement.empty() || secondElement.empty()) + if (firstElement.empty()) return {}; + if (secondElement.empty()) + return { firstElement }; vector intersection = ElementsIntersection(firstElement, secondElement); vector> result; @@ -188,7 +190,7 @@ bool AccessingSet::ContainsElement(const vector& element) const { vector> tails; FindUncovered(element, tails); - return !tails.empty(); + return tails.empty(); } void AccessingSet::FindCoveredBy(const vector& element, vector>& result) const @@ -252,13 +254,15 @@ AccessingSet AccessingSet::Diff(const AccessingSet& secondSet) const return *this; AccessingSet intersection = this->Intersect(secondSet); - AccessingSet uncovered = *this; - vector> result; - for (const auto& element : intersection.GetElements()) + vector> uncovered; + for (const auto& element : allElements) { vector> current_uncovered; - uncovered.FindUncovered(element, current_uncovered); - uncovered = AccessingSet(current_uncovered); + intersection.FindUncovered(element, current_uncovered); + uncovered.insert(uncovered.end(), + std::move_iterator(current_uncovered.begin()), + std::move_iterator(current_uncovered.end()) + ); } return uncovered; } diff --git a/src/PrivateAnalyzer/region.cpp b/src/PrivateAnalyzer/region.cpp index 4b58cd3..8b7db70 100644 --- a/src/PrivateAnalyzer/region.cpp +++ b/src/PrivateAnalyzer/region.cpp @@ -1,8 +1,9 @@ -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include #include @@ -94,7 +95,7 @@ static string FindIndexName(int pos, SAPFOR::BasicBlock* block, mapgetInstructions(); map loopForIndex; BuildLoopIndex(loopForIndex, loop); @@ -124,7 +125,11 @@ static int GetDefUseArray(SAPFOR::BasicBlock* block, LoopGraph* loop, ArrayAcces } if (point.size() == dimCount) - def[instruction->getInstruction()->getResult()->getValue()] = AccessingSet({point}); + { + def[instruction->getInstruction()->getResult()->getValue()] = AccessingSet({ point }); + RegionInstruction regionInstruction; + regionInstruction.def[instruction->getInstruction()->getResult()->getValue()] = AccessingSet({ point }); + } } } } @@ -149,21 +154,21 @@ static int GetDefUseArray(SAPFOR::BasicBlock* block, LoopGraph* loop, ArrayAcces auto* ref = isSgArrayRefExp(instruction->getInstruction()->getExpression()); int fillCount = 0; - vector> coefsForDims; + vector> coeffsForDims; int subs = ref->numberOfSubscripts(); for (int i = 0; ref && i < ref->numberOfSubscripts(); ++i) { - const vector& coefs = getAttributes(ref->subscript(i), set{ INT_VAL }); - if (coefs.size() == 1) + const vector& coeffs = getAttributes(ref->subscript(i), set{ INT_VAL }); + if (coeffs.size() == 1) { - const pair coef(coefs[0][0], coefs[0][1]); - coefsForDims.push_back(coef); + const pair coef(coeffs[0][0], coeffs[0][1]); + coeffsForDims.push_back(coef); } } - coefsForDims = {coefsForDims.rbegin(), coefsForDims.rend()}; + coeffsForDims = {coeffsForDims.rbegin(), coeffsForDims.rend()}; - while (!index_vars.empty() && !refPos.empty() && !coefsForDims.empty()) + while (!index_vars.empty() && !refPos.empty() && !coeffsForDims.empty()) { auto var = index_vars.back(); int currentVarPos = refPos.back(); @@ -195,7 +200,7 @@ static int GetDefUseArray(SAPFOR::BasicBlock* block, LoopGraph* loop, ArrayAcces return -1; } - uint64_t start = coefsForDims.back().second * currentLoop->startVal + coefsForDims.back().first; + uint64_t start = coeffsForDims.back().second * currentLoop->startVal + coeffsForDims.back().first; uint64_t step = currentLoop->stepVal; uint64_t iters = currentLoop->calculatedCountOfIters; current_dim = { start, step, iters, ref }; @@ -208,15 +213,30 @@ static int GetDefUseArray(SAPFOR::BasicBlock* block, LoopGraph* loop, ArrayAcces } index_vars.pop_back(); refPos.pop_back(); - coefsForDims.pop_back(); + coeffsForDims.pop_back(); } if (fillCount == accessPoint.size()) { + RegionInstruction instruction; if (operation == SAPFOR::CFG_OP::STORE) + { def[array_name].Insert(accessPoint); + instruction.def[array_name] = { { accessPoint } }; + } else - use[array_name].Insert(accessPoint); + { + instruction.use[array_name] = { { accessPoint } }; + all_use[array_name].Insert(accessPoint); + if (def.find(array_name) == def.end()) + use[array_name].Insert(accessPoint); + else + { + AccessingSet element({ accessPoint }); + use[array_name] = use[array_name].Union(element.Diff(def[array_name])); + } + } + region->instructions.push_back(instruction); } } } @@ -224,6 +244,41 @@ static int GetDefUseArray(SAPFOR::BasicBlock* block, LoopGraph* loop, ArrayAcces } +static void RemoveHeaderConnection(SAPFOR::BasicBlock* header, const unordered_set& blockSet, unordered_map& bbToRegion) +{ + for (SAPFOR::BasicBlock* block : blockSet) + { + bool isCycleBlock = false; + for (SAPFOR::BasicBlock* prevBlock : block->getPrev()) + isCycleBlock = isCycleBlock || (blockSet.find(prevBlock) != blockSet.end()); + + if (isCycleBlock) + { + bbToRegion[block]->removeNextRegion(bbToRegion[header]); + bbToRegion[header]->removePrevRegion(bbToRegion[block]); + } + } +} + +static void DFS(Region* block, vector& result, unordered_set cycleBlocks) +{ + for (Region* nextBlock : block->getNextRegions()) + { + if (cycleBlocks.find(nextBlock) != cycleBlocks.end()) + DFS(nextBlock, result, cycleBlocks); + } + result.push_back(block); +} + +void TopologySort(std::vector& basikBlocks, Region* header) +{ + vector result; + unordered_set cycleBlocks(basikBlocks.begin(), basikBlocks.end()); + DFS(header, result, cycleBlocks); + reverse(result.begin(), result.end()); + basikBlocks = result; +} + static void SetConnections(unordered_map& bbToRegion, const unordered_set& blockSet) { for (SAPFOR::BasicBlock* block : blockSet) @@ -238,10 +293,11 @@ static void SetConnections(unordered_map& bbToRegi } } -static Region* CreateSubRegion(LoopGraph* loop, const vector& Blocks, const unordered_map& bbToRegion) +static Region* CreateSubRegion(LoopGraph* loop, const vector& Blocks, unordered_map& bbToRegion) { Region* region = new Region; auto [header, blockSet] = GetBasicBlocksForLoop(loop, Blocks); + RemoveHeaderConnection(header, blockSet, bbToRegion); if (bbToRegion.find(header) != bbToRegion.end()) region->setHeader(bbToRegion.at(header)); else @@ -253,13 +309,14 @@ static Region* CreateSubRegion(LoopGraph* loop, const vectoraddBasickBlocks(bbToRegion.at(block)); - + for (LoopGraph* childLoop : loop->children) { if (!childLoop->isFor()) continue; region->addSubRegions(CreateSubRegion(childLoop, Blocks, bbToRegion)); } + TopologySort(region->getBasickBlocks(), region->getHeader()); return region; } @@ -270,12 +327,13 @@ Region::Region(LoopGraph* loop, const vector& Blocks) for (auto poiner : blockSet) { bbToRegion[poiner] = new Region(*poiner); - this->basickBlocks.insert(bbToRegion[poiner]); - GetDefUseArray(poiner, loop, bbToRegion[poiner]->array_def, bbToRegion[poiner]->array_use); + this->basickBlocks.push_back(bbToRegion[poiner]); + GetDefUseArray(poiner, loop, bbToRegion[poiner]->array_def, bbToRegion[poiner]->array_use, bbToRegion[poiner]->array_all_use, bbToRegion[poiner]); } this->header = bbToRegion[header]; SetConnections(bbToRegion, blockSet); + RemoveHeaderConnection(header, blockSet, bbToRegion); //create subRegions for (LoopGraph* childLoop : loop->children) { @@ -283,4 +341,5 @@ Region::Region(LoopGraph* loop, const vector& Blocks) continue; subRegions.insert(CreateSubRegion(childLoop, Blocks, bbToRegion)); } + TopologySort(basickBlocks, this->header); } diff --git a/src/PrivateAnalyzer/region.h b/src/PrivateAnalyzer/region.h index 935460f..1665b1d 100644 --- a/src/PrivateAnalyzer/region.h +++ b/src/PrivateAnalyzer/region.h @@ -8,6 +8,11 @@ #include "graph_loops.h" #include "CFGraph/CFGraph.h" +struct RegionInstruction +{ + ArrayAccessingIndexes def, use, in, out; +}; + class Region : public SAPFOR::BasicBlock { public: Region() { header = nullptr; } @@ -20,13 +25,25 @@ public: void setHeader(Region* region) { header = region; } - std::unordered_set& getBasickBlocks() { return basickBlocks; } + std::vector& getBasickBlocks() { return basickBlocks; } - void addBasickBlocks(Region* region) { basickBlocks.insert(region); } + void addBasickBlocks(Region* region) { basickBlocks.push_back(region); } const std::unordered_set& getPrevRegions() { return prevRegions; } - std::unordered_set getNextRegions() { return nextRegions; } + std::unordered_set& getNextRegions() { return nextRegions; } + + void removeNextRegion(Region* region) + { + if (nextRegions.find(region) != nextRegions.end()) + nextRegions.erase(region); + } + + void removePrevRegion(Region* region) + { + if (prevRegions.find(region) != prevRegions.end()) + prevRegions.erase(region); + } void addPrevRegion(Region* region) { prevRegions.insert(region); } @@ -48,13 +65,18 @@ public: void addSubRegions(Region* region) { subRegions.insert(region); } - ArrayAccessingIndexes array_def, array_use, array_out, array_in, array_priv; + std::vector instructions; + + ArrayAccessingIndexes array_def, array_use, array_out, array_in, array_priv, array_all_use; private: - std::unordered_set subRegions, basickBlocks; + std::vector basickBlocks; + std::unordered_set subRegions; /*next Region which is BB for current BB Region*/ std::unordered_set nextRegions; /*prev Regions which is BBs for current BB Region*/ std::unordered_set prevRegions; Region* header; }; + +void TopologySort(std::vector& basikBlocks, Region* header);