From e8ecc8491d074bdcc8c6312bded2343ad7ef8898 Mon Sep 17 00:00:00 2001 From: Oleg Nikitin Date: Mon, 31 Mar 2025 02:50:30 +0300 Subject: [PATCH] add Collapse --- CMakeLists.txt | 4 +- src/PrivateAnalyzer/private_arrays_search.cpp | 590 ++++++++++++++++++ src/PrivateAnalyzer/private_arrays_search.h | 84 +++ 3 files changed, 677 insertions(+), 1 deletion(-) create mode 100644 src/PrivateAnalyzer/private_arrays_search.cpp create mode 100644 src/PrivateAnalyzer/private_arrays_search.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 87eb86c..1b0f054 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,7 +113,9 @@ set(OMEGA src/SageAnalysisTool/OmegaForSage/add-assert.cpp src/SageAnalysisTool/set.cpp) set(PRIV src/PrivateAnalyzer/private_analyzer.cpp - src/PrivateAnalyzer/private_analyzer.h) + src/PrivateAnalyzer/private_analyzer.h + src/PrivateAnalyzer/private_arrays_search.cpp + src/PrivateAnalyzer/private_arrays_search.h) set(FDVM ${fdvm_sources}/acc.cpp ${fdvm_sources}/acc_across.cpp diff --git a/src/PrivateAnalyzer/private_arrays_search.cpp b/src/PrivateAnalyzer/private_arrays_search.cpp new file mode 100644 index 0000000..084cbcc --- /dev/null +++ b/src/PrivateAnalyzer/private_arrays_search.cpp @@ -0,0 +1,590 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "private_arrays_search.h" +#include "../Utils/SgUtils.h" +#include "../GraphLoop/graph_loops.h" +#include "../CFGraph/CFGraph.h" + +using namespace std; + +void print_info(LoopGraph* loop) +{ + cout << "loopSymbol: " << loop->loopSymbol << endl; + for (const auto& ops : loop->writeOpsForLoop) + { + cout << "Array name: " << ops.first->GetShortName() << endl; + for (const auto i : ops.second) + { + i.printInfo(); + } + } + if (!loop->children.empty()) + { + for (const auto child : loop->children) + { + print_info(child); + } + } +} + +static bool isParentStmt(SgStatement* stmt, SgStatement* parent) +{ + for (; stmt; stmt = stmt->controlParent()) + if (stmt == parent) + { + return true; + } + return false; +} + +/*returns head block and loop*/ +static pair> GetBasicBlocksForLoop(LoopGraph* loop, vector blocks) +{ + unordered_set block_loop; + SAPFOR::BasicBlock* head_block = nullptr; + auto loop_operator = loop->loop->GetOriginal(); + for (const auto& block : blocks) + { + if (!block || (block->getInstructions().size() == 0)) + { + continue; + } + SgStatement* first = block->getInstructions().front()->getInstruction()->getOperator(); + SgStatement* last = block->getInstructions().back()->getInstruction()->getOperator(); + if (isParentStmt(first, loop_operator) && isParentStmt(last, loop_operator)) + { + block_loop.insert(block); + + if ((!head_block) && (first == loop_operator) && (last == loop_operator) && + (block->getInstructions().size() == 2) && + (block->getInstructions().back()->getInstruction()->getOperation() == SAPFOR::CFG_OP::JUMP_IF)) + { + head_block = block; + } + + } + } + return { head_block, block_loop }; +} + + +static void BuildLoopIndex(map& loopForIndex, LoopGraph* loop) { + string index = loop->loopSymbol; + loopForIndex[index] = loop; + for (const auto& childLoop : loop->children) { + BuildLoopIndex(loopForIndex, childLoop); + } +} + +static string FindIndexName(int pos, SAPFOR::BasicBlock* block, map& loopForIndex) { + unordered_set args = {block->getInstructions()[pos]->getInstruction()->getArg1()}; + + for (int i = pos-1; i >= 0; i--) { + SAPFOR::Argument* res = block->getInstructions()[i]->getInstruction()->getResult(); + if (res && args.find(res) != args.end()) { + SAPFOR::Argument* arg1 = block->getInstructions()[i]->getInstruction()->getArg1(); + SAPFOR::Argument* arg2 = block->getInstructions()[i]->getInstruction()->getArg2(); + if (arg1) { + string name = arg1->getValue(); + int idx = name.find('%'); + if (idx != -1 && loopForIndex.find(name.substr(idx + 1)) != loopForIndex.end()) + return name.substr(idx + 1); + else { + args.insert(arg1); + } + } + if (arg2) { + string name = arg2->getValue(); + int idx = name.find('%'); + if (idx != -1 && loopForIndex.find(name.substr(idx + 1)) != loopForIndex.end()) + return name.substr(idx + 1); + else { + args.insert(arg2); + } + } + } + } + return ""; +} + +static int GetDefUseArray(SAPFOR::BasicBlock* block, LoopGraph* loop, ArrayAccessingIndexes& def, ArrayAccessingIndexes& use) { + auto instructions = block->getInstructions(); + map loopForIndex; + BuildLoopIndex(loopForIndex, loop); + for(int i = 0; i < instructions.size(); i++) + { + auto instruction = instructions[i]; + if(!instruction->getInstruction()->getArg1()) { + continue; + } + auto operation = instruction->getInstruction()->getOperation(); + auto type = instruction->getInstruction()->getArg1()->getType(); + if ((operation == SAPFOR::CFG_OP::STORE || operation == SAPFOR::CFG_OP::LOAD) && type == SAPFOR::CFG_ARG_TYPE::ARRAY) + { + vector index_vars; + vector refPos; + string array_name; + if (operation == SAPFOR::CFG_OP::STORE) + { + array_name = instruction->getInstruction()->getArg1()->getValue(); + } + else + { + array_name = instruction->getInstruction()->getArg2()->getValue(); + } + int j = i - 1; + while (j >= 0 && instructions[j]->getInstruction()->getOperation() == SAPFOR::CFG_OP::REF) + { + index_vars.push_back(instructions[j]->getInstruction()->getArg1()); + refPos.push_back(j); + j--; + } + /*to choose correct dimension*/ + int n = index_vars.size(); + vector accessPoint(n); + /*if (operation == SAPFOR::CFG_OP::STORE) + { + if (def[array_name].empty()) + { + def[array_name].resize(n); + } + } + else + { + if (use[array_name].empty()) + { + use[array_name].resize(n); + } + }*/ + + SgArrayRefExp* ref = (SgArrayRefExp*)instruction->getInstruction()->getExpression(); + vector> coefsForDims; + for (int i = 0; i < ref->numberOfSubscripts(); ++i) + { + const vector& coefs = getAttributes(ref->subscript(i), set{ INT_VAL }); + if (coefs.size() == 1) + { + const pair coef(coefs[0][0], coefs[0][1]); + coefsForDims.push_back(coef); + } + + } + + while (!index_vars.empty()) + { + auto var = index_vars.back(); + int currentVarPos = refPos.back(); + pair currentCoefs = coefsForDims.back(); + ArrayDimension current_dim; + if (var->getType() == SAPFOR::CFG_ARG_TYPE::CONST) { + current_dim = { stoul(var->getValue()), 1, 1 }; + } + else + { + string name, full_name = var->getValue(); + int pos = full_name.find('%'); + LoopGraph* currentLoop; + if (pos != -1) { + name = full_name.substr(pos+1); + if (loopForIndex.find(name) != loopForIndex.end()) { + currentLoop = loopForIndex[name]; + } + else { + return -1; + } + } + else { + name = FindIndexName(currentVarPos, block, loopForIndex); + if (name == "") { + return -1; + } + if (loopForIndex.find(name) != loopForIndex.end()) { + currentLoop = loopForIndex[name]; + } + else { + return -1; + } + } + uint64_t start = currentLoop->startVal * currentCoefs.first + currentCoefs.second; + uint64_t step = currentCoefs.first; + current_dim = { start, step, (uint64_t)currentLoop->calculatedCountOfIters }; + } + /*if (operation == SAPFOR::CFG_OP::STORE) + { + def[array_name][n - index_vars.size()].push_back(current_dim); + } + else + { + use[array_name][n - index_vars.size()].push_back(current_dim); + }*/ + accessPoint[n - index_vars.size()] = current_dim; + index_vars.pop_back(); + refPos.pop_back(); + coefsForDims.pop_back(); + } + if (operation == SAPFOR::CFG_OP::STORE) + { + def[array_name].Insert(accessPoint); + } + else + { + use[array_name].Insert(accessPoint); + } + } + } + return 0; + +} + +static vector FindParticularSolution(const ArrayDimension& dim1, const ArrayDimension& dim2) +{ + for (uint64_t i = 0; i < dim1.tripCount; i++) + { + uint64_t leftPart = dim1.start + i * dim1.step; + for (uint64_t j = 0; j < dim2.tripCount; j++) + { + uint64_t rightPart = dim2.start + j * dim2.step; + if (leftPart == rightPart) + { + return {i, j}; + } + } + } + return {}; +} + +/* dim1 /\ dim2 */ +static ArrayDimension* DimensionIntersection(const ArrayDimension& dim1, const ArrayDimension& dim2) +{ + vector partSolution = FindParticularSolution(dim1, dim2); + if (partSolution.empty()) + { + return NULL; + } + int64_t x0 = partSolution[0], y0 = partSolution[1]; + /* x = x_0 + c * t */ + /* y = y_0 + d * t */ + int64_t c = dim2.step / gcd(dim1.step, dim2.step); + int64_t d = dim1.step / gcd(dim1.step, dim2.step); + int64_t tXMin, tXMax, tYMin, tYMax; + tXMin = -x0 / c; + tXMax = (dim1.tripCount - 1 - x0) / c; + tYMin = -y0 / d; + tYMax = (dim2.tripCount - 1 - y0) / d; + int64_t tMin = max(tXMin, tYMin); + uint64_t tMax = min(tXMax, tYMax); + if (tMin > tMax) + { + return NULL; + } + uint64_t start3 = dim1.start + x0 * dim1.step; + uint64_t step3 = c * dim1.step; + ArrayDimension* result = new(ArrayDimension){ start3, step3, tMax + 1 }; + return result; +} + +/* dim1 / dim2 */ +static vector DimensionDifference(const ArrayDimension& dim1, const ArrayDimension& dim2) +{ + ArrayDimension* intersection = DimensionIntersection(dim1, dim2); + if (!intersection) + { + return {dim1}; + } + vector result; + /* add the part before intersection */ + if (dim1.start < intersection->start) + { + result.push_back({ dim1.start, dim1.step, (intersection->start - dim1.start) / dim1.step }); + } + /* add the parts between intersection steps */ + uint64_t start = (intersection->start - dim1.start) / dim1.step; + uint64_t interValue = intersection->start; + for (int64_t i = start; dim1.start + i * dim1.step <= intersection->start + intersection->step * (intersection->tripCount - 1); i++) + { + uint64_t centerValue = dim1.start + i * dim1.step; + if (centerValue == interValue) + { + if (i - start > 1) + { + result.push_back({ dim1.start + (start + 1) * dim1.step, dim1.step, i - start - 1 }); + start = i; + } + interValue += intersection->step; + } + } + /* add the part after intersection */ + if (intersection->start + intersection->step * (intersection->tripCount - 1) < dim1.start + dim1.step * (dim1.tripCount - 1)) + { + /* first value after intersection */ + uint64_t right_start = intersection->start + intersection->step * (intersection->tripCount - 1) + dim1.step; + uint64_t tripCount = (dim1.start + dim1.step * dim1.tripCount - right_start) / dim1.step; + result.push_back({right_start, dim1.step, tripCount}); + } + delete(intersection); + return result; +} + + +static vector DimensionUnion(const ArrayDimension& dim1, const ArrayDimension& dim2) +{ + vector res; + ArrayDimension* inter = DimensionIntersection(dim1, dim2); + if(!inter) + { + return { dim1, dim2 }; + } + res.push_back(*inter); + delete(inter); + vector diff1, diff2; + diff1 = DimensionDifference(dim1, dim2); + diff2 = DimensionDifference(dim2, dim1); + res.insert(res.end(), diff1.begin(), diff1.end()); + res.insert(res.end(), diff2.begin(), diff2.end()); + return res; +} + +static vector ElementsIntersection(const vector& firstElement, const vector& secondElement) +{ + if(firstElement.empty() || secondElement.empty()) { + return {}; + } + size_t dimAmount = firstElement.size(); + /* check if there is no intersecction */ + for(size_t i = 0; i < dimAmount; i++) + { + if(FindParticularSolution(firstElement[i], secondElement[i]).empty()){ + return {}; + } + } + vector result(dimAmount); + for(size_t i = 0; i < dimAmount; i++) + { + ArrayDimension* resPtr = DimensionIntersection(firstElement[i], secondElement[i]); + if(resPtr) + { + result[i] = *resPtr; + } + else + { + return {}; + } + } + return result; +} + +static vector> ElementsDifference(const vector& firstElement, + const vector& secondElement) +{ + if(firstElement.empty() || secondElement.empty()) { + return {}; + } + vector intersection = ElementsIntersection(firstElement, secondElement); + vector> result; + if(intersection.empty()) + { + return {firstElement}; + } + for(int i = 0; i < firstElement.size(); i++) + { + auto dimDiff = DimensionDifference(firstElement[i], secondElement[i]); + if(!dimDiff.empty()) + { + vector firstCopy = firstElement; + for(const auto range: dimDiff) + { + firstCopy[i] = range; + result.push_back(firstCopy); + } + } + } + return result; +} + +static void ElementsUnion(const vector& firstElement, const vector& secondElement, + vector>& lc, vector>& rc, + vector& intersection) +{ + /* lc(rc) is a set of ranges, which only exist in first(second) element*/ + intersection = ElementsIntersection(firstElement, secondElement); + lc = ElementsDifference(firstElement, intersection); + rc = ElementsDifference(secondElement, intersection); +} + +void AccessingSet::FindUncovered(const vector& element, vector>& result) const{ + vector> newTails; + result.push_back(element); + for(const auto& currentElement: allElements) + { + for(const auto& tailLoc: result) + { + auto intersection = ElementsIntersection(tailLoc, currentElement); + auto diff = ElementsDifference(tailLoc, intersection); + if(!diff.empty()) { + newTails.insert(newTails.end(), diff.begin(), diff.end()); + } + } + result = move(newTails); + } +} + +bool AccessingSet::ContainsElement(const vector& element) const +{ + vector> tails; + FindUncovered(element, tails); + return !tails.empty(); +} + +void AccessingSet::FindCoveredBy(const vector& element, vector>& result) const +{ + for(const auto& currentElement: allElements) + { + auto intersection = ElementsIntersection(element, currentElement); + if(!intersection.empty()) { + result.push_back(intersection); + } + } +} + +vector> AccessingSet::GetElements() const +{ + return allElements; +} + +void AccessingSet::Insert(const vector& element) +{ + vector> tails; + FindUncovered(element, tails); + allElements.insert(allElements.end(), tails.begin(), tails.end()); +} + +void AccessingSet::Union(const AccessingSet& source) { + for(auto& element: source.GetElements()) { + Insert(element); + } +} + +AccessingSet AccessingSet::Intersect(const AccessingSet& secondSet) const +{ + vector> result; + for(const auto& element: allElements) + { + if(secondSet.ContainsElement(element)) + { + result.push_back(element); + } + else + { + vector> coveredBy; + secondSet.FindCoveredBy(element, coveredBy); + if(!coveredBy.empty()) + { + result.insert(result.end(), coveredBy.begin(), coveredBy.end()); + } + } + } + return AccessingSet(result); +} + +AccessingSet AccessingSet::Diff(const AccessingSet& secondSet) const +{ + AccessingSet intersection = this->Intersect(secondSet); + AccessingSet uncovered = *this; + vector> result; + for (const auto& element : intersection.GetElements()) + { + vector> current_uncovered; + uncovered.FindUncovered(element, current_uncovered); + uncovered = AccessingSet(current_uncovered); + } + return uncovered; +} + +void Collapse(Region* region) +{ + Region* newBlock = new Region(); + for (auto& [arrayName, arrayRanges] : region->GetHeader()->array_out) + { + for (Region* byBlock : region->GetBasickBlocks()) + { + AccessingSet intersection = byBlock->array_def[arrayName].Intersect(arrayRanges); + newBlock->array_def[arrayName].Union(intersection); + } + } + + for (auto& byBlock : region->GetBasickBlocks()) { + for (auto& [arrayName, arrayRanges] : byBlock->array_use) + { + AccessingSet diff = byBlock->array_use[arrayName].Diff(byBlock->array_in[arrayName]); + newBlock->array_use[arrayName].Union(diff); + } + } + for (Region* prevRegion : region->getPrevRegions()) { + prevRegion->setNextRegion(newBlock); + } + region->getNextRegion()->setPrevRegion(newBlock); +} + +void FindPrivateArrays(map> &loopGraph, map>& FullIR) +{ + for (const auto& curr_graph_pair: loopGraph) + { + for (const auto& curr_loop : curr_graph_pair.second) + { + auto block_loop = GetBasicBlocksForLoop(curr_loop, (*FullIR.begin()).second); + for (const auto& bb : block_loop.second) { + ArrayAccessingIndexes def, use; + //GetDefUseArray(bb, curr_loop, def, use); + } + ArrayAccessingIndexes loopDimensionsInfo; + //GetDimensionInfo(curr_loop, loopDimensionsInfo, 0); + //print_info(curr_loop); + } + } + +} + +void GetDimensionInfo(LoopGraph* loop, map>>& loopDimensionsInfo, int level) +{ + cout << "line_num: " << loop->lineNum << endl; + for (const auto& writeOpPairs : loop->writeOpsForLoop) + { + vector> arrayDimensions(writeOpPairs.first->GetDimSize()); + loopDimensionsInfo[writeOpPairs.first] = arrayDimensions; + for (const auto& writeOp : writeOpPairs.second) + { + for (const auto& coeficient_pair : writeOp.coefficients) + { + uint64_t start, step, tripCount; + start = loop->startVal * coeficient_pair.first.first + coeficient_pair.first.second; + step = loop->stepVal * coeficient_pair.first.first; + tripCount = (loop->endVal - coeficient_pair.first.second) / step; + if (start <= loop->endVal) + { + loopDimensionsInfo[writeOpPairs.first][level].push_back({start, step, tripCount}); + cout << "level: " << level << endl; + cout << "start: " << start << endl; + cout << "step: " << step << endl; + cout << "trip_count: " << tripCount << endl; + cout << endl; + } + + + } + } + } + cout << "line_num_after: " << loop->lineNumAfterLoop << endl; + if (!loop->children.empty()) + { + for (const auto& childLoop : loop->children) + { + GetDimensionInfo(childLoop, loopDimensionsInfo, level+1); + } + } +} diff --git a/src/PrivateAnalyzer/private_arrays_search.h b/src/PrivateAnalyzer/private_arrays_search.h new file mode 100644 index 0000000..d146d52 --- /dev/null +++ b/src/PrivateAnalyzer/private_arrays_search.h @@ -0,0 +1,84 @@ +#pragma once + +#include "../GraphLoop/graph_loops.h" +#include "../CFGraph/CFGraph.h" + +using std::vector; +using std::map; +using std::string; +using std::set; + +struct ArrayDimension +{ + uint64_t start, step, tripCount; +}; + +class AccessingSet { + private: + vector> allElements; + + public: + AccessingSet(vector> input) : allElements(input) {}; + AccessingSet() {}; + vector> GetElements() const; + void Insert(const vector& element); + void Union(const AccessingSet& source); + AccessingSet Intersect(const AccessingSet& secondSet) const; + AccessingSet Diff(const AccessingSet& secondSet) const; + bool ContainsElement(const vector& element) const; + void FindCoveredBy(const vector& element, vector>& result) const; + void FindUncovered(const vector& element, vector>& result) const; +}; + +using ArrayAccessingIndexes = map; + +class Region: public SAPFOR::BasicBlock { + public: + Region() + { + header = nullptr; + nextRegion = nullptr; + } + Region(SAPFOR::BasicBlock block) : SAPFOR::BasicBlock::BasicBlock(block) + { + header = nullptr; + nextRegion = nullptr; + }; + //Region(LoopGraph* loop); + Region* GetHeader() + { + return header; + } + set GetBasickBlocks() + { + return basickBlocks; + } + vector getPrevRegions() + { + return prevRegions; + } + Region* getNextRegion() + { + return nextRegion; + } + void setPrevRegion(Region* region) + { + prevRegions.push_back(region); + } + void setNextRegion(Region* region) + { + nextRegion = region; + } + ArrayAccessingIndexes array_def, array_use, array_out, array_in; + + private: + set subRegions, basickBlocks; + Region* header; + Region* nextRegion; + vector prevRegions; +}; + +void Collapse(Region* region); +void FindPrivateArrays(map>& loopGraph, map>& FullIR); +void GetDimensionInfo(LoopGraph* loop, map>>& loopDimensionsInfo, int level); +set GetBasicBlocksForLoop(LoopGraph* loop, vector);