From be3904a256978907f902fbb896000cedcba8a477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20H=C3=B6lscher?= Date: Fri, 29 Apr 2022 14:31:08 +0200 Subject: [PATCH 1/5] WIP --- .vscode/launch.json | 15 ++++ CacheAnalysisPass/CacheAnalysisPass.cpp | 49 +---------- include/AbstractCache.h | 112 +++++++++++++++++++++++- include/AbstractState.h | 34 +++++-- 4 files changed, 151 insertions(+), 59 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index e769ab8..bfa1036 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,6 +4,21 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "LLDB cnt", + "program": "/usr/bin/opt", + "args": [ + "-load-pass-plugin", + "${workspaceFolder}/build/libCacheAnalysisPass.so", + "-passes=lru-misses", + "${workspaceFolder}/test/cnt.ll", + "-o", + "/dev/null" + ], + "cwd": "${workspaceFolder}" + }, { "type": "lldb", "request": "launch", diff --git a/CacheAnalysisPass/CacheAnalysisPass.cpp b/CacheAnalysisPass/CacheAnalysisPass.cpp index 47a6ed7..4e253d0 100644 --- a/CacheAnalysisPass/CacheAnalysisPass.cpp +++ b/CacheAnalysisPass/CacheAnalysisPass.cpp @@ -46,52 +46,6 @@ using namespace llvm; // everything in an anonymous namespace. namespace { -std::string typeToName(Type::TypeID Id) { - switch (Id) { - case Type::TypeID::ArrayTyID: - return "ArrayTy"; - case Type::TypeID::BFloatTyID: - return "BFloatTy"; - case Type::TypeID::FloatTyID: - return "FloatTy"; - case Type::TypeID::DoubleTyID: - return "DoubleTy"; - case Type::TypeID::FixedVectorTyID: - return "FixedVectorTy"; - case Type::TypeID::FP128TyID: - return "FP128Ty"; - case Type::TypeID::FunctionTyID: - return "FunctionTy"; - case Type::TypeID::HalfTyID: - return "HalfTy"; - case Type::TypeID::IntegerTyID: - return "IntegerTy"; - case Type::TypeID::LabelTyID: - return "LabelTy"; - case Type::TypeID::MetadataTyID: - return "MetadataTy"; - case Type::TypeID::PointerTyID: - return "PointerTy"; - case Type::TypeID::PPC_FP128TyID: - return "PPC_FP128Ty"; - case Type::TypeID::ScalableVectorTyID: - return "ScalableVectorTy"; - case Type::TypeID::StructTyID: - return "StructTy"; - case Type::TypeID::TokenTyID: - return "TokenTy"; - case Type::TypeID::VoidTyID: - return "VoidTy"; - case Type::TypeID::X86_AMXTyID: - return "X86_AMXTy"; - case Type::TypeID::X86_FP80TyID: - return "X86_FP80Ty"; - case Type::TypeID::X86_MMXTyID: - return "X86_MMXTy"; - } - // should not reach here - return nullptr; -} // New PM implementation struct CacheAnalysisPass : PassInfoMixin { @@ -100,7 +54,7 @@ struct CacheAnalysisPass : PassInfoMixin { bool PrintAddresses = false; bool PrintEdges = false; bool PrintEdgesPost = false; - bool DumpToDot = false; + bool DumpToDot = true; bool DumpNodes = false; // Assume a 4kB Cache @@ -278,6 +232,7 @@ struct CacheAnalysisPass : PassInfoMixin { AC.dumpEdges(); if (DumpToDot) AC.dumpDotFile(); + AC.unrollLoops(); AC.fillAbstractCache(EntryAddress); if (DumpNodes) AC.dumpNodes(); diff --git a/include/AbstractCache.h b/include/AbstractCache.h index f4b47e5..48df8e7 100644 --- a/include/AbstractCache.h +++ b/include/AbstractCache.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -29,6 +30,7 @@ public: // everything is public, because IDGAF // map keys are instruction Addresses. std::map> Edges; std::map Nodes; + unsigned int NumberOfNodes = 0; AbstractCache() {} @@ -44,17 +46,112 @@ public: // everything is public, because IDGAF Nodes[Suc].Predecessors.push_back(Pre); } - void addEmptyNode(unsigned int NodeAddr) { - Nodes[NodeAddr] = AbstractState(NodeAddr); + unsigned int addEmptyNode(unsigned int NodeAddr) { + Nodes[NumberOfNodes++] = AbstractState(NodeAddr); + return NumberOfNodes; } + /** + * @brief Unroll Loops. + * + * @param NodeNr + */ + void unrollLoops() { + for (auto NodePair : Nodes) { + unsigned int NodeNr = NodePair.first; + if (NodeNr == 34) { + llvm::outs() << "HI\n"; + } + bool IsLoopHead = false; + bool FoundLoopBody = false; + bool Verbose = true; + std::list LoopBody; + if (Nodes[NodeNr].Predecessors.size() > 1) { + IsLoopHead = true; + // is loop head? + for (unsigned int Pre : Nodes[NodeNr].Predecessors) { + if (Pre > NodeNr) { + // Might be loop head. + // check if all States between Pre and NodeNr are a coherent set. + for (uint I = NodeNr; I < Pre; I++) { + LoopBody.push_back(I); + for (uint Succ : Nodes[I].Successors) { + if (Succ > Pre) { + // Set is not coherent + IsLoopHead = false; + break; + } + } + FoundLoopBody = true; + } + LoopBody.push_back(Pre); + } else if (!FoundLoopBody) { + // If no coherent Loopbody exist we cannot unroll. + LoopBody.clear(); + IsLoopHead = false; + } + } + } + if (IsLoopHead && Verbose) { + llvm::outs() << "Found LoopHead @: " << NodeNr << "\n"; + llvm::outs() << "With Body: {\n"; + int I = 1; + for (auto Node : LoopBody) { + llvm::outs() << Node << ", "; + if (!(I++ % 5)) { + llvm::outs() << "\n"; + } + } + llvm::outs() << "}\n"; + } + // Found Loop Head and Body! + // TODO: Now unroll + // Add empty unrolled Nodes + // Map points from OrigNode To Unrolled Node. + std::map OrigNodeToUnrolledNode; + for (auto Node : LoopBody) { + // Node to unroll + AbstractState UnrolledNode(Nodes[Node]); + UnrolledNode.setUnrolled(1); + Nodes[NumberOfNodes++] = UnrolledNode; + OrigNodeToUnrolledNode[Node] = NumberOfNodes; + } + + unsigned int LoopHead = LoopBody.front(); + LoopBody.pop_front(); + unsigned int LoopTail = LoopBody.back(); + LoopBody.pop_back(); + for (auto Node : LoopBody) { + for (auto Succ : Nodes[Node].Successors) { + // Add All successors to unrolled Node + Nodes[OrigNodeToUnrolledNode[Node]].Successors.push_back( + OrigNodeToUnrolledNode[Succ]); + } + for (auto Pre : Nodes[Node].Predecessors) { + // Add All predecessors to unrolled Node + Nodes[OrigNodeToUnrolledNode[Node]].Successors.push_back( + OrigNodeToUnrolledNode[Pre]); + } + } + } + return; + } + + /** + * @brief Idea fill the graph with the node and perform loop unrolling. + * + * @param NodeNr + */ void fillAbstractCache(unsigned int NodeNr) { + // if(isLoopHead(NodeNr)) + // unrollLoop(NodeNr); Nodes[NodeNr].Computed = true; for (unsigned int SuccNr : Nodes[NodeNr].Successors) { Nodes[SuccNr]; if (Nodes[SuccNr].Computed) { // Join don't call - Nodes[SuccNr].mustJoin(Nodes[NodeNr]); + // TODO fix Join + Nodes[SuccNr].mustJoin(Nodes[NodeNr]); // maybe fill Nodes[SuccNr].mustJoin(AbstractState(NodeNr)); } else { // Update and fill Succ @@ -107,13 +204,20 @@ public: // everything is public, because IDGAF } void dumpDotFile() { + bool PrintOld = true; std::ofstream DotFile; DotFile.open("out.dot"); DotFile << "digraph g {" << "\n"; for (auto const &E : Edges) { for (unsigned int To : E.second) { - DotFile << E.first << " -> " << To << "\n"; + if (PrintOld) { + DotFile << E.first << " -> " << To << "\n"; + } else { + DotFile << Nodes[E.first].Addr << "." << Nodes[E.first].Unrolled + << " -> " << Nodes[To].Addr << "." << Nodes[To].Unrolled + << "\n"; + } } } DotFile << "}\n"; diff --git a/include/AbstractState.h b/include/AbstractState.h index 3251353..1b4da84 100644 --- a/include/AbstractState.h +++ b/include/AbstractState.h @@ -27,6 +27,7 @@ public: // everything is public, because IDGAF std::list Predecessors; unsigned int Addr; + unsigned int Unrolled; bool Computed = false; @@ -57,6 +58,8 @@ public: // everything is public, because IDGAF std::map Sets; AbstractState(AbstractState const &Copy) { + Addr = Copy.Addr; + Unrolled = Copy.Unrolled; for (auto S : Copy.Sets) { unsigned int SetNr = S.first; for (auto E : S.second.Associativity) { @@ -70,12 +73,22 @@ public: // everything is public, because IDGAF AbstractState() {} - AbstractState(unsigned int AddressIn) { Addr = AddressIn; } - - AbstractState(Address Addr) { - Sets[Addr.Index].Associativity[0] = {{Addr.Tag}}; + AbstractState(unsigned int AddressIn) { + Addr = AddressIn; + Unrolled = 0; } + AbstractState(unsigned int AddressIn, unsigned int UnrolledIn) { + Addr = AddressIn; + Unrolled = UnrolledIn; + } + + // AbstractState(Address Addr) { + // Sets[Addr.Index].Associativity[0] = {{Addr.Tag}}; + // } + + void setUnrolled(unsigned int In) { Unrolled = In; } + /** * @brief Executes an Must LRU Join on the AbstractCacheState * @@ -111,9 +124,11 @@ public: // everything is public, because IDGAF * @param Addr , Address */ void update(Address Addr) { + // This loopages all entries by one. 3 <-2, 2<-1, 1<-0 for (int I = 3; I > 0; I--) { Sets[Addr.Index].Associativity[I] = Sets[Addr.Index].Associativity[I - 1]; } + // entry at age 0 is updated with current address. Sets[Addr.Index].Associativity[0].Blocks = {Addr.Tag}; } @@ -126,7 +141,7 @@ public: // everything is public, because IDGAF for (auto S : UpdateState.Sets) { unsigned int Index = S.first; for (auto E : S.second.Associativity) { - unsigned int Age = E.first + 1; + unsigned int Age = E.first; // If updated age is greater 4 The Tag is no longer in Cache. // Due to associativity of 4 per set. if (Age >= 4) @@ -139,17 +154,18 @@ public: // everything is public, because IDGAF } /** - * @brief Fills the AbstractState PreState and PreAddress. + * @brief Fills the AbstractState PreState and updates with PreAddress. * * @param PreState, State that fills this state. * * @param PreAddr Address of PreState */ void fill(AbstractState PreState, Address PreAddr) { + // copy Pre State into this. for (auto S : PreState.Sets) { unsigned int Index = S.first; for (auto E : S.second.Associativity) { - unsigned int Age = E.first + 1; + unsigned int Age = E.first; // If updated age is greater 4 The Tag is no longer in Cache. // Due to associativity of 4 per set. if (Age >= 4) @@ -159,11 +175,13 @@ public: // everything is public, because IDGAF } } } - Sets[PreAddr.Index].Associativity[0].Blocks.push_back(PreAddr.Tag); + // update this with PreAddr + this->update(PreAddr); } void dump() { llvm::outs() << Addr << " {\n"; + llvm::outs() << "Unrolled: " << Unrolled << "\n"; llvm::outs() << "Predecessors: "; for (auto PreNr : Predecessors) { llvm::outs() << PreNr << " "; From 5e6e0e6c9080e5e13b4ff9d222651327f2b47e2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20H=C3=B6lscher?= Date: Tue, 3 May 2022 11:13:37 +0200 Subject: [PATCH 2/5] first Version of Loop Unrolling --- .vscode/launch.json | 4 +- CacheAnalysisPass/CacheAnalysisPass.cpp | 10 +- helper.sh | 70 +++--- include/AbstractCache.h | 317 ++++++++++++++++++++---- 4 files changed, 304 insertions(+), 97 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index bfa1036..eb3a209 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -7,13 +7,13 @@ { "type": "lldb", "request": "launch", - "name": "LLDB cnt", + "name": "LLDB Unrolling", "program": "/usr/bin/opt", "args": [ "-load-pass-plugin", "${workspaceFolder}/build/libCacheAnalysisPass.so", "-passes=lru-misses", - "${workspaceFolder}/test/cnt.ll", + "${workspaceFolder}/test/fft1.ll", "-o", "/dev/null" ], diff --git a/CacheAnalysisPass/CacheAnalysisPass.cpp b/CacheAnalysisPass/CacheAnalysisPass.cpp index 4e253d0..f0d85e3 100644 --- a/CacheAnalysisPass/CacheAnalysisPass.cpp +++ b/CacheAnalysisPass/CacheAnalysisPass.cpp @@ -56,6 +56,7 @@ struct CacheAnalysisPass : PassInfoMixin { bool PrintEdgesPost = false; bool DumpToDot = true; bool DumpNodes = false; + bool LoopUnrolling = true; // Assume a 4kB Cache // with 16 Sets, associativity of 4 and Cachelines fitting two @@ -228,14 +229,15 @@ struct CacheAnalysisPass : PassInfoMixin { if (PrintAddresses) addressPrinter(F); } + if(LoopUnrolling) + AC.unrollLoops(); + AC.fillAbstractCache(EntryAddress); + if (DumpNodes) + AC.dumpNodes(); if (PrintEdgesPost) AC.dumpEdges(); if (DumpToDot) AC.dumpDotFile(); - AC.unrollLoops(); - AC.fillAbstractCache(EntryAddress); - if (DumpNodes) - AC.dumpNodes(); outs() << "MustHits: " << AC.collectHits() << "\n"; outs() << "MayMisses: " << AC.collectMisses() << "\n"; return PreservedAnalyses::all(); diff --git a/helper.sh b/helper.sh index 6693d95..ee575c6 100755 --- a/helper.sh +++ b/helper.sh @@ -114,46 +114,36 @@ case $1 in echo "Currently not available!" echo "But please continue to implement the must join," echo "to the best of your abilities and check for updates!" - # run "fft1" - # echo "==== Correct fft1 ====" - # echo "MustHits: 16" - # echo "MayMisses: 280" - # echo - # run "bsort100" - # echo "==== Correct bsort100 ====" - # echo "MustHits: 1" - # echo "MayMisses: 41" - # echo - # run "lms" - # echo "==== Correct lms ====" - # echo "MustHits: 5" - # echo "MayMisses: 288" - # echo - # run "minver" - # echo "==== Correct minver ====" - # echo "MustHits: 6" - # echo "MayMisses: 224" - # echo - # run "qsort-exam" - # echo "==== Correct qsort-exam ====" - # echo "MustHits: 2" - # echo "MayMisses: 152" - # echo - # run "recursion" - # echo "==== Correct recursion ====" - # echo "MustHits: 8" - # echo "MayMisses: 8" - # echo - # run "select" - # echo "==== Correct select ====" - # echo "MustHits: 4" - # echo "MayMisses: 108" - # echo - # run "whet" - # echo "==== Correct whet ====" - # echo "MustHits: 5" - # echo "MayMisses: 265" - # echo + run "fft1" + echo "==== Correct fft1 ====" + echo "MustHits: 16" + echo "MayMisses: 280" + echo + run "cnt" + echo "==== Correct cnt ====" + echo "MustHits: x" + echo "MayMisses: xx" + echo + run "crc" + echo "==== Correct crc ====" + echo "MustHits: x" + echo "MayMisses: xx" + echo + run "duff" + echo "==== Correct duff ====" + echo "MustHits: x" + echo "MayMisses: xx" + echo + run "insertsort" + echo "==== Correct insertsort ====" + echo "MustHits: x" + echo "MayMisses: xx" + echo + run "matmult" + echo "==== Correct matmult ====" + echo "MustHits: x" + echo "MayMisses: x" + echo ;; a | all) clean diff --git a/include/AbstractCache.h b/include/AbstractCache.h index 48df8e7..bc522c9 100644 --- a/include/AbstractCache.h +++ b/include/AbstractCache.h @@ -30,7 +30,6 @@ public: // everything is public, because IDGAF // map keys are instruction Addresses. std::map> Edges; std::map Nodes; - unsigned int NumberOfNodes = 0; AbstractCache() {} @@ -46,9 +45,120 @@ public: // everything is public, because IDGAF Nodes[Suc].Predecessors.push_back(Pre); } + /** + * @brief Add an Edge to the AbstractStateGraph + * + * @param Pre + * @param Suc + */ + void removeEdge(unsigned int Pre, unsigned int Suc) { + Edges[Pre].remove(Suc); + Nodes[Pre].Successors.remove(Suc); + Nodes[Suc].Predecessors.remove(Pre); + } + + /** + * @brief Add an Empty node @NodeAddr + * + * @param NodeAddr + * @return unsigned int + */ unsigned int addEmptyNode(unsigned int NodeAddr) { - Nodes[NumberOfNodes++] = AbstractState(NodeAddr); - return NumberOfNodes; + int I = Nodes.size(); + Nodes[I] = AbstractState(NodeAddr); + return I; + } + + /** + * @brief Returns True if a path From -> To exists. + * + * @param From + * @param To + * @return true + * @return false + */ + bool findPath(unsigned int From, unsigned int To) { + std::map Visited; + Visited[From] = false; + bool Ret = false; + for (auto Visitor : Visited) { + if (!Visitor.second) { + for (unsigned int Next : Edges[Visitor.first]) { + if (Next == To) { + return true; + } + Visited[Next] = false; + } + } + Visited[Visitor.first] = true; + } + return false; + } + + /** + * @brief Removes all Nested loops from the handed LoopBody + * + * @param LoopBodyIn + * @param OrigNodeToUnrolledNode + */ + void removeNestedLoops( + std::list LoopBodyIn, + std::map OrigNodeToUnrolledNode) { + unsigned int LoopHead = LoopBodyIn.front(); + unsigned int LoopTail = LoopBodyIn.back(); + unsigned int NestLoopTail; + for (unsigned int NodeNr : LoopBodyIn) { + bool IsLoopHead = false; + bool FoundLoopBody = false; + unsigned int LoopBodySize = 0; + int NestLoopHead = 0; + NestLoopHead = NodeNr; + if (Nodes[NodeNr].Predecessors.size() > 1) { + IsLoopHead = true; + FoundLoopBody = false; + LoopBodySize++; + // is loop head? + for (unsigned int Pre : Nodes[NodeNr].Predecessors) { + if (Pre > NodeNr) { + // Might be loop head. + // check if all States between Pre and NodeNr are a coherent set. + for (unsigned int I = NodeNr; I < Pre; I++) { + // Check if all out going edges are in the set + for (unsigned int Succ : Nodes[I].Successors) { + if (Succ > Pre) { + // Set is not coherent + IsLoopHead = false; + break; + } + } + // check if all incoming edges are in the set. + if (IsLoopHead && I != NodeNr) + for (unsigned int Pred : Nodes[I].Predecessors) { + if (Pred < NodeNr) { + // Set is not coherent + IsLoopHead = false; + break; + } + } + FoundLoopBody = true; + LoopBodySize++; + } + NestLoopTail = Pre; + } else if (!FoundLoopBody) { + // If no coherent Loopbody exist we cannot unroll. + NestLoopHead = 0; + IsLoopHead = false; + } + if (FoundLoopBody) { + // Check if a Path between Head and Tail exists, + // if not its not a loop. + if (findPath(NestLoopHead, NestLoopTail)) + removeEdge(OrigNodeToUnrolledNode[NestLoopTail], + OrigNodeToUnrolledNode[NestLoopHead]); + } + } + } + } } /** @@ -57,15 +167,23 @@ public: // everything is public, because IDGAF * @param NodeNr */ void unrollLoops() { - for (auto NodePair : Nodes) { - unsigned int NodeNr = NodePair.first; - if (NodeNr == 34) { - llvm::outs() << "HI\n"; + unsigned int NestedBorder = 0; + unsigned int LastNode = Nodes.size(); + unsigned int IterationCounter = 0; + for (std::pair NodePair : Nodes) { + IterationCounter++; + if (NodePair.first == LastNode) { + break; } + unsigned int NodeNr = NodePair.first; + // Don't unroll nested loops + if (NodeNr < NestedBorder) + continue; bool IsLoopHead = false; bool FoundLoopBody = false; - bool Verbose = true; + bool Verbose = false; std::list LoopBody; + std::list AdditionalLoopTails; if (Nodes[NodeNr].Predecessors.size() > 1) { IsLoopHead = true; // is loop head? @@ -73,15 +191,42 @@ public: // everything is public, because IDGAF if (Pre > NodeNr) { // Might be loop head. // check if all States between Pre and NodeNr are a coherent set. - for (uint I = NodeNr; I < Pre; I++) { - LoopBody.push_back(I); - for (uint Succ : Nodes[I].Successors) { - if (Succ > Pre) { - // Set is not coherent - IsLoopHead = false; - break; + for (unsigned int I = NodeNr; I < Pre; I++) { + // Check if all out going edges are in the set + for (unsigned int Succ : Nodes[I].Successors) { + for (unsigned int PreI : Nodes[I].Predecessors) { + // Handle if we have multiple Loopheads. + if (PreI >= Pre && I != NodeNr) { + // I and Pre are Looptail. + { + if (std::find(AdditionalLoopTails.begin(), + AdditionalLoopTails.end(), + I) == AdditionalLoopTails.end()) { + AdditionalLoopTails.push_back(I); + break; + } + } + } + if (std::find(LoopBody.begin(), LoopBody.end(), I) == + LoopBody.end()) + LoopBody.push_back(I); + + if (Succ > Pre) { + // Set is not coherent + IsLoopHead = false; + break; + } } } + // check if all incoming edges are in the set. + if (IsLoopHead && I != NodeNr) + for (unsigned int Pred : Nodes[I].Predecessors) { + if (Pred < NodeNr) { + // Set is not coherent + IsLoopHead = false; + break; + } + } FoundLoopBody = true; } LoopBody.push_back(Pre); @@ -92,45 +237,91 @@ public: // everything is public, because IDGAF } } } - if (IsLoopHead && Verbose) { - llvm::outs() << "Found LoopHead @: " << NodeNr << "\n"; - llvm::outs() << "With Body: {\n"; - int I = 1; - for (auto Node : LoopBody) { - llvm::outs() << Node << ", "; - if (!(I++ % 5)) { - llvm::outs() << "\n"; - } - } - llvm::outs() << "}\n"; - } // Found Loop Head and Body! - // TODO: Now unroll // Add empty unrolled Nodes // Map points from OrigNode To Unrolled Node. - std::map OrigNodeToUnrolledNode; - for (auto Node : LoopBody) { - // Node to unroll - AbstractState UnrolledNode(Nodes[Node]); - UnrolledNode.setUnrolled(1); - Nodes[NumberOfNodes++] = UnrolledNode; - OrigNodeToUnrolledNode[Node] = NumberOfNodes; - } - - unsigned int LoopHead = LoopBody.front(); - LoopBody.pop_front(); - unsigned int LoopTail = LoopBody.back(); - LoopBody.pop_back(); - for (auto Node : LoopBody) { - for (auto Succ : Nodes[Node].Successors) { - // Add All successors to unrolled Node - Nodes[OrigNodeToUnrolledNode[Node]].Successors.push_back( - OrigNodeToUnrolledNode[Succ]); + if (FoundLoopBody) { + std::map OrigNodeToUnrolledNode; + for (unsigned int Node : LoopBody) { + // Node to unroll + AbstractState UnrolledNode(Nodes[Node]); + UnrolledNode.setUnrolled(1); + unsigned int I = Nodes.size(); + Nodes[I] = UnrolledNode; + OrigNodeToUnrolledNode[Node] = I; + assert(Nodes[OrigNodeToUnrolledNode[Node]].Unrolled == 1); + assert(Nodes[Node].Addr == Nodes[OrigNodeToUnrolledNode[Node]].Addr); } - for (auto Pre : Nodes[Node].Predecessors) { - // Add All predecessors to unrolled Node - Nodes[OrigNodeToUnrolledNode[Node]].Successors.push_back( - OrigNodeToUnrolledNode[Pre]); + + // LoopTail and Head have to be processed different + unsigned int LoopTail = LoopBody.back(); + LoopBody.pop_back(); + NestedBorder = LoopTail; + unsigned int LoopHead = LoopBody.front(); + LoopBody.pop_front(); + + // Find State entering to LoopHead () + unsigned int LoopHeadEntry = 0; + for (unsigned int Pre : Nodes[LoopHead].Predecessors) { + if (Pre < LoopHead) { + LoopHeadEntry = Pre; + break; + } + } + + // Make LoopHeadEntry point to unrolled state instead of the loop. + addEdge(LoopHeadEntry, OrigNodeToUnrolledNode[LoopHead]); + removeEdge(LoopHeadEntry, LoopHead); + // Connect unrolled Loop to the the original Loop. + if (AdditionalLoopTails.size() == 0) + addEdge(OrigNodeToUnrolledNode[LoopTail], LoopHead); + for (auto Tail : AdditionalLoopTails) + addEdge(OrigNodeToUnrolledNode[Tail], LoopHead); + + // Fix all other states + addEdge(OrigNodeToUnrolledNode[LoopBody.back()], + OrigNodeToUnrolledNode[LoopTail]); + for (unsigned int Node : LoopBody) { + for (unsigned int Pre : Nodes[Node].Predecessors) { + // if (std::find(LoopBody.begin(), LoopBody.end(), Pre) != + // LoopBody.end()) + // Add All predecessors and successors to unrolled Nodes + addEdge(OrigNodeToUnrolledNode[Pre], OrigNodeToUnrolledNode[Node]); + } + } + + // Remove Nested loops in unrolled loop + removeNestedLoops(LoopBody, OrigNodeToUnrolledNode); + + if (Verbose && FoundLoopBody) { + llvm::outs() << "Found LoopHead @: " << NodeNr << "\n"; + llvm::outs() << "With LoopTail @: " << LoopTail << "\n"; + llvm::outs() << "With Body: {\n"; + int I = 1; + for (auto Node : LoopBody) { + llvm::outs() << Node << ", "; + if (!(I++ % 5)) { + llvm::outs() << "\n"; + } + } + llvm::outs() << "}\n"; + llvm::outs() << "Unrolled States: {\n"; + I = 1; + for (auto Node : LoopBody) { + llvm::outs() << OrigNodeToUnrolledNode[Node] << ", "; + if (!(I++ % 5)) { + llvm::outs() << "\n"; + } + } + llvm::outs() << "}\n"; + I = 1; + llvm::outs() << "OrigNodeToUnrolledNode: {\n"; + for (auto Nr : OrigNodeToUnrolledNode) { + llvm::outs() << Nr.first << "->" << Nr.second << ", "; + if (!(I++ % 3)) + llvm::outs() << "\n"; + } + llvm::outs() << "}\n"; } } } @@ -144,7 +335,6 @@ public: // everything is public, because IDGAF */ void fillAbstractCache(unsigned int NodeNr) { // if(isLoopHead(NodeNr)) - // unrollLoop(NodeNr); Nodes[NodeNr].Computed = true; for (unsigned int SuccNr : Nodes[NodeNr].Successors) { Nodes[SuccNr]; @@ -162,6 +352,11 @@ public: // everything is public, because IDGAF return; } + /** + * @brief Return number of measured Hits + * + * @return unsigned int + */ unsigned int collectHits() { unsigned int Hits = 0; for (auto const &E : Edges) { @@ -174,6 +369,11 @@ public: // everything is public, because IDGAF return Hits; } + /** + * @brief Return number of measured Misses + * + * @return unsigned int + */ unsigned int collectMisses() { unsigned int Misses = 0; for (auto const &E : Edges) { @@ -186,6 +386,10 @@ public: // everything is public, because IDGAF return Misses; } + /** + * @brief Prints all Edges to Console + * + */ void dumpEdges() { llvm::outs() << "Dumping Edges:\n"; for (auto const &E : Edges) { @@ -203,6 +407,10 @@ public: // everything is public, because IDGAF } } + /** + * @brief Dumps the Graph to a out.dot file + * + */ void dumpDotFile() { bool PrintOld = true; std::ofstream DotFile; @@ -213,6 +421,9 @@ public: // everything is public, because IDGAF for (unsigned int To : E.second) { if (PrintOld) { DotFile << E.first << " -> " << To << "\n"; + if (Nodes[E.first].Unrolled) { + DotFile << E.first << " [color = red]\n"; + } } else { DotFile << Nodes[E.first].Addr << "." << Nodes[E.first].Unrolled << " -> " << Nodes[To].Addr << "." << Nodes[To].Unrolled @@ -224,6 +435,10 @@ public: // everything is public, because IDGAF DotFile.close(); } + /** + * @brief Prints all nodes to Console + * + */ void dumpNodes() { for (auto const &E : Edges) { Nodes[E.first].dump(); From 693ee07008e545c2a6f6f28aaa3c5b41575882c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20H=C3=B6lscher?= Date: Tue, 3 May 2022 14:04:21 +0200 Subject: [PATCH 3/5] Joining until state converges. Added Eval Again. --- .gitignore | 1 + CacheAnalysisPass/CacheAnalysisPass.cpp | 3 +- helper.sh | 27 +++------ include/AbstractCache.h | 53 ++++++++-------- include/AbstractState.h | 81 +++++++++++++++++++------ poolhelper.sh | 67 ++++++++------------ 6 files changed, 126 insertions(+), 106 deletions(-) diff --git a/.gitignore b/.gitignore index e2f0333..e275226 100644 --- a/.gitignore +++ b/.gitignore @@ -7,5 +7,6 @@ build/ .gnupg .bash_history .cache/ +*.solution compile_commands.json llvm/ \ No newline at end of file diff --git a/CacheAnalysisPass/CacheAnalysisPass.cpp b/CacheAnalysisPass/CacheAnalysisPass.cpp index f0d85e3..ff6795b 100644 --- a/CacheAnalysisPass/CacheAnalysisPass.cpp +++ b/CacheAnalysisPass/CacheAnalysisPass.cpp @@ -232,6 +232,7 @@ struct CacheAnalysisPass : PassInfoMixin { if(LoopUnrolling) AC.unrollLoops(); AC.fillAbstractCache(EntryAddress); + //AC.fillPath(EntryAddress); if (DumpNodes) AC.dumpNodes(); if (PrintEdgesPost) @@ -239,7 +240,7 @@ struct CacheAnalysisPass : PassInfoMixin { if (DumpToDot) AC.dumpDotFile(); outs() << "MustHits: " << AC.collectHits() << "\n"; - outs() << "MayMisses: " << AC.collectMisses() << "\n"; + //outs() << "MayMisses: " << AC.collectMisses() << "\n"; return PreservedAnalyses::all(); } }; diff --git a/helper.sh b/helper.sh index ee575c6..7c36001 100755 --- a/helper.sh +++ b/helper.sh @@ -111,38 +111,29 @@ case $1 in docker run -i -d -v "$(pwd)"/.:/root:rw --name RTSAlab01 rtsalab01cacheanalysis ;; evaluation | eval) - echo "Currently not available!" - echo "But please continue to implement the must join," - echo "to the best of your abilities and check for updates!" run "fft1" echo "==== Correct fft1 ====" - echo "MustHits: 16" - echo "MayMisses: 280" + echo "MustHits: 21" echo run "cnt" echo "==== Correct cnt ====" - echo "MustHits: x" - echo "MayMisses: xx" - echo - run "crc" - echo "==== Correct crc ====" - echo "MustHits: x" - echo "MayMisses: xx" + echo "MustHits: 4" echo run "duff" echo "==== Correct duff ====" - echo "MustHits: x" - echo "MayMisses: xx" + echo "MustHits: 3" echo run "insertsort" echo "==== Correct insertsort ====" - echo "MustHits: x" - echo "MayMisses: xx" + echo "MustHits: 2" echo run "matmult" echo "==== Correct matmult ====" - echo "MustHits: x" - echo "MayMisses: x" + echo "MustHits: 9" + echo + run "crc" + echo "==== Correct crc ====" + echo "MustHits: 6" echo ;; a | all) diff --git a/include/AbstractCache.h b/include/AbstractCache.h index bc522c9..3040dd3 100644 --- a/include/AbstractCache.h +++ b/include/AbstractCache.h @@ -47,9 +47,9 @@ public: // everything is public, because IDGAF /** * @brief Add an Edge to the AbstractStateGraph - * - * @param Pre - * @param Suc + * + * @param Pre + * @param Suc */ void removeEdge(unsigned int Pre, unsigned int Suc) { Edges[Pre].remove(Suc); @@ -59,9 +59,9 @@ public: // everything is public, because IDGAF /** * @brief Add an Empty node @NodeAddr - * - * @param NodeAddr - * @return unsigned int + * + * @param NodeAddr + * @return unsigned int */ unsigned int addEmptyNode(unsigned int NodeAddr) { int I = Nodes.size(); @@ -71,11 +71,11 @@ public: // everything is public, because IDGAF /** * @brief Returns True if a path From -> To exists. - * - * @param From - * @param To - * @return true - * @return false + * + * @param From + * @param To + * @return true + * @return false */ bool findPath(unsigned int From, unsigned int To) { std::map Visited; @@ -97,9 +97,9 @@ public: // everything is public, because IDGAF /** * @brief Removes all Nested loops from the handed LoopBody - * - * @param LoopBodyIn - * @param OrigNodeToUnrolledNode + * + * @param LoopBodyIn + * @param OrigNodeToUnrolledNode */ void removeNestedLoops( std::list LoopBodyIn, @@ -338,11 +338,16 @@ public: // everything is public, because IDGAF Nodes[NodeNr].Computed = true; for (unsigned int SuccNr : Nodes[NodeNr].Successors) { Nodes[SuccNr]; + // first Run if (Nodes[SuccNr].Computed) { // Join don't call - // TODO fix Join - Nodes[SuccNr].mustJoin(Nodes[NodeNr]); // maybe fill - Nodes[SuccNr].mustJoin(AbstractState(NodeNr)); + AbstractState Before(Nodes[SuccNr]); + Nodes[SuccNr].mustJoin(AbstractState(NodeNr, Address(NodeNr))); + + // Continue Joining until State converges + if (!(Before == Nodes[SuccNr])) { + fillAbstractCache(NodeNr); + } } else { // Update and fill Succ Nodes[SuccNr].fill(Nodes[NodeNr], NodeNr); @@ -354,8 +359,8 @@ public: // everything is public, because IDGAF /** * @brief Return number of measured Hits - * - * @return unsigned int + * + * @return unsigned int */ unsigned int collectHits() { unsigned int Hits = 0; @@ -371,8 +376,8 @@ public: // everything is public, because IDGAF /** * @brief Return number of measured Misses - * - * @return unsigned int + * + * @return unsigned int */ unsigned int collectMisses() { unsigned int Misses = 0; @@ -388,7 +393,7 @@ public: // everything is public, because IDGAF /** * @brief Prints all Edges to Console - * + * */ void dumpEdges() { llvm::outs() << "Dumping Edges:\n"; @@ -409,7 +414,7 @@ public: // everything is public, because IDGAF /** * @brief Dumps the Graph to a out.dot file - * + * */ void dumpDotFile() { bool PrintOld = true; @@ -437,7 +442,7 @@ public: // everything is public, because IDGAF /** * @brief Prints all nodes to Console - * + * */ void dumpNodes() { for (auto const &E : Edges) { diff --git a/include/AbstractState.h b/include/AbstractState.h index 1b4da84..1d4fa21 100644 --- a/include/AbstractState.h +++ b/include/AbstractState.h @@ -1,6 +1,7 @@ #ifndef ABSSTATE_H #define ABSSTATE_H +#include #include #include #include @@ -71,6 +72,21 @@ public: // everything is public, because IDGAF } } + AbstractState(AbstractState const &Copy, Address Update) { + Addr = Copy.Addr; + Unrolled = Copy.Unrolled; + for (auto S : Copy.Sets) { + unsigned int SetNr = S.first; + for (auto E : S.second.Associativity) { + unsigned int Age = E.first; + for (auto B : E.second.Blocks) { + Sets[SetNr].Associativity[Age].Blocks.push_back(B); + } + } + } + this->update(Update); + } + AbstractState() {} AbstractState(unsigned int AddressIn) { @@ -89,6 +105,30 @@ public: // everything is public, because IDGAF void setUnrolled(unsigned int In) { Unrolled = In; } + bool operator==(AbstractState In) { + for (int Index; Index < 16; Index++) { + for (int Age; Age < 4; Age++) { + for (auto E1 : Sets[Index].Associativity[Age].Blocks) { + // find E1 in In States Set and Age. + if (std::find(In.Sets[Index].Associativity[Age].Blocks.begin(), + In.Sets[Index].Associativity[Age].Blocks.end(), + E1) == In.Sets[Index].Associativity[Age].Blocks.end()) { + return false; + } + } + for (auto E2 : In.Sets[Index].Associativity[Age].Blocks) { + // find E2 in This Set and Age. + if (std::find(Sets[Index].Associativity[Age].Blocks.begin(), + Sets[Index].Associativity[Age].Blocks.end(), + E2) == Sets[Index].Associativity[Age].Blocks.end()) { + return false; + } + } + } + } + return true; + } + /** * @brief Executes an Must LRU Join on the AbstractCacheState * @@ -127,31 +167,32 @@ public: // everything is public, because IDGAF // This loopages all entries by one. 3 <-2, 2<-1, 1<-0 for (int I = 3; I > 0; I--) { Sets[Addr.Index].Associativity[I] = Sets[Addr.Index].Associativity[I - 1]; + Sets[Addr.Index].Associativity[I].Blocks.remove(Addr.Tag); } // entry at age 0 is updated with current address. Sets[Addr.Index].Associativity[0].Blocks = {Addr.Tag}; } - /** - * @brief Updates the AbstractState with given AbstractState - * - * @param UpdateState, State that gets merged into State with Age+1. - */ - void update(AbstractState UpdateState) { - for (auto S : UpdateState.Sets) { - unsigned int Index = S.first; - for (auto E : S.second.Associativity) { - unsigned int Age = E.first; - // If updated age is greater 4 The Tag is no longer in Cache. - // Due to associativity of 4 per set. - if (Age >= 4) - break; - for (auto B : E.second.Blocks) { - Sets[Index].Associativity[Age].Blocks.push_back(B); - } - } - } - } + // /** + // * @brief Updates the AbstractState with given AbstractState + // * + // * @param UpdateState, State that gets merged into State with Age+1. + // */ + // void update(AbstractState UpdateState) { + // for (auto S : UpdateState.Sets) { + // unsigned int Index = S.first; + // for (auto E : S.second.Associativity) { + // unsigned int Age = E.first; + // // If updated age is greater 4 The Tag is no longer in Cache. + // // Due to associativity of 4 per set. + // if (Age >= 4) + // break; + // for (auto B : E.second.Blocks) { + // Sets[Index].Associativity[Age].Blocks.push_back(B); + // } + // } + // } + // } /** * @brief Fills the AbstractState PreState and updates with PreAddress. diff --git a/poolhelper.sh b/poolhelper.sh index 9918002..d20d2a3 100755 --- a/poolhelper.sh +++ b/poolhelper.sh @@ -145,49 +145,30 @@ case $1 in docker run -i -d -v "$(pwd)"/.:/root:rw --name RTSAlab01 rtsalab01cacheanalysis ;; evaluation | eval) - echo "Currently not available!" - echo "But please continue to implement the must join," - echo "to the best of your abilities and check for updates!" - # run "fft1" - # echo "==== Correct fft1 ====" - # echo "MustHits: 16" - # echo "MayMisses: 280" - # echo - # run "bsort100" - # echo "==== Correct bsort100 ====" - # echo "MustHits: 1" - # echo "MayMisses: 41" - # echo - # run "lms" - # echo "==== Correct lms ====" - # echo "MustHits: 5" - # echo "MayMisses: 288" - # echo - # run "minver" - # echo "==== Correct minver ====" - # echo "MustHits: 6" - # echo "MayMisses: 224" - # echo - # run "qsort-exam" - # echo "==== Correct qsort-exam ====" - # echo "MustHits: 2" - # echo "MayMisses: 152" - # echo - # run "recursion" - # echo "==== Correct recursion ====" - # echo "MustHits: 8" - # echo "MayMisses: 8" - # echo - # run "select" - # echo "==== Correct select ====" - # echo "MustHits: 4" - # echo "MayMisses: 108" - # echo - # run "whet" - # echo "==== Correct whet ====" - # echo "MustHits: 5" - # echo "MayMisses: 265" - # echo + run "fft1" + echo "==== Correct fft1 ====" + echo "MustHits: 21" + echo + run "cnt" + echo "==== Correct cnt ====" + echo "MustHits: 4" + echo + run "duff" + echo "==== Correct duff ====" + echo "MustHits: 3" + echo + run "insertsort" + echo "==== Correct insertsort ====" + echo "MustHits: 2" + echo + run "matmult" + echo "==== Correct matmult ====" + echo "MustHits: 9" + echo + run "crc" + echo "==== Correct crc ====" + echo "MustHits: 6" + echo ;; a | all) clean From c451a1eed080aadd8dc9df4105798e0c99508339 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20H=C3=B6lscher?= Date: Tue, 3 May 2022 14:10:24 +0200 Subject: [PATCH 4/5] No longer Dumping Dotfile as default. --- CacheAnalysisPass/CacheAnalysisPass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CacheAnalysisPass/CacheAnalysisPass.cpp b/CacheAnalysisPass/CacheAnalysisPass.cpp index ff6795b..d02b5dd 100644 --- a/CacheAnalysisPass/CacheAnalysisPass.cpp +++ b/CacheAnalysisPass/CacheAnalysisPass.cpp @@ -54,7 +54,7 @@ struct CacheAnalysisPass : PassInfoMixin { bool PrintAddresses = false; bool PrintEdges = false; bool PrintEdgesPost = false; - bool DumpToDot = true; + bool DumpToDot = false; bool DumpNodes = false; bool LoopUnrolling = true; From 3429652f452081ce04b59b7e798c35bd118bf916 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20H=C3=B6lscher?= Date: Fri, 6 May 2022 10:04:45 +0200 Subject: [PATCH 5/5] Correct MustAnalysis. --- .vscode/launch.json | 2 +- CacheAnalysisPass/CacheAnalysisPass.cpp | 3 +- helper.sh | 22 ++++++------ include/AbstractCache.h | 46 ++++++++++++++----------- include/AbstractState.h | 41 ++++++++++------------ poolhelper.sh | 22 ++++++------ 6 files changed, 69 insertions(+), 67 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index eb3a209..aa8dcd9 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -13,7 +13,7 @@ "-load-pass-plugin", "${workspaceFolder}/build/libCacheAnalysisPass.so", "-passes=lru-misses", - "${workspaceFolder}/test/fft1.ll", + "${workspaceFolder}/test/cnt.ll", "-o", "/dev/null" ], diff --git a/CacheAnalysisPass/CacheAnalysisPass.cpp b/CacheAnalysisPass/CacheAnalysisPass.cpp index d02b5dd..97c4d2a 100644 --- a/CacheAnalysisPass/CacheAnalysisPass.cpp +++ b/CacheAnalysisPass/CacheAnalysisPass.cpp @@ -231,8 +231,7 @@ struct CacheAnalysisPass : PassInfoMixin { } if(LoopUnrolling) AC.unrollLoops(); - AC.fillAbstractCache(EntryAddress); - //AC.fillPath(EntryAddress); + AC.runMustAnalysis(EntryAddress); if (DumpNodes) AC.dumpNodes(); if (PrintEdgesPost) diff --git a/helper.sh b/helper.sh index 7c36001..c4138d6 100755 --- a/helper.sh +++ b/helper.sh @@ -111,29 +111,29 @@ case $1 in docker run -i -d -v "$(pwd)"/.:/root:rw --name RTSAlab01 rtsalab01cacheanalysis ;; evaluation | eval) - run "fft1" - echo "==== Correct fft1 ====" - echo "MustHits: 21" + run "crc" + echo "==== Correct crc ====" + echo "MustHits: 90" echo run "cnt" echo "==== Correct cnt ====" - echo "MustHits: 4" + echo "MustHits: 28" echo run "duff" echo "==== Correct duff ====" - echo "MustHits: 3" + echo "MustHits: 78" + echo + run "fft1" + echo "==== Correct fft1 ====" + echo "MustHits: 74" echo run "insertsort" echo "==== Correct insertsort ====" - echo "MustHits: 2" + echo "MustHits: 61" echo run "matmult" echo "==== Correct matmult ====" - echo "MustHits: 9" - echo - run "crc" - echo "==== Correct crc ====" - echo "MustHits: 6" + echo "MustHits: 34" echo ;; a | all) diff --git a/include/AbstractCache.h b/include/AbstractCache.h index 3040dd3..b4cf544 100644 --- a/include/AbstractCache.h +++ b/include/AbstractCache.h @@ -329,29 +329,35 @@ public: // everything is public, because IDGAF } /** - * @brief Idea fill the graph with the node and perform loop unrolling. + * @brief Perform must analysis in the Graph * * @param NodeNr */ - void fillAbstractCache(unsigned int NodeNr) { - // if(isLoopHead(NodeNr)) - Nodes[NodeNr].Computed = true; - for (unsigned int SuccNr : Nodes[NodeNr].Successors) { - Nodes[SuccNr]; - // first Run - if (Nodes[SuccNr].Computed) { - // Join don't call - AbstractState Before(Nodes[SuccNr]); - Nodes[SuccNr].mustJoin(AbstractState(NodeNr, Address(NodeNr))); + void runMustAnalysis(unsigned int NodeNr) { + // Join and call until the state converges. - // Continue Joining until State converges - if (!(Before == Nodes[SuccNr])) { - fillAbstractCache(NodeNr); - } + Nodes[NodeNr].Computed++; + + // fill all Successors, if filled Already join. + for (unsigned int SuccNr : Nodes[NodeNr].Successors) { + if (Nodes[SuccNr].Filled) { + // Join Successor with current State and its Address + Nodes[SuccNr].mustJoin( + AbstractState(Nodes[NodeNr], Address(Nodes[NodeNr].Addr))); } else { - // Update and fill Succ - Nodes[SuccNr].fill(Nodes[NodeNr], NodeNr); - fillAbstractCache(SuccNr); + // Fill Successor with current State and its Address + Nodes[SuccNr].fill(Nodes[NodeNr], Address(Nodes[NodeNr].Addr)); + // first Fill, so set Filled + Nodes[SuccNr].Filled = true; + } + + // Continue Filling CFG on Successors. + for (unsigned int SuccNr : Nodes[NodeNr].Successors) { + // We can use this as we can safely assume a State has at most two successors. + // Due to branch instruction in llvmIR + if (Nodes[NodeNr].Computed > 2) + continue; + runMustAnalysis(SuccNr); } } return; @@ -368,7 +374,7 @@ public: // everything is public, because IDGAF auto Predecessor = Nodes[E.first]; for (unsigned int SuccessorAddr : E.second) { // When successors Address is in predecessor, we have a Hit. - Hits += Predecessor.isHit(Address(SuccessorAddr)) ? 1 : 0; + Hits += Predecessor.isHit(Address(Nodes[SuccessorAddr].Addr)) ? 1 : 0; } } return Hits; @@ -385,7 +391,7 @@ public: // everything is public, because IDGAF auto Predecessor = Nodes[E.first]; for (unsigned int SuccessorAddr : E.second) { // When successors Address is in predecessor, we have a Hit. - Misses += Predecessor.isHit(Address(SuccessorAddr)) ? 0 : 1; + Misses += Predecessor.isHit(Address(Nodes[SuccessorAddr].Addr)) ? 0 : 1; } } return Misses; diff --git a/include/AbstractState.h b/include/AbstractState.h index 1d4fa21..46149d6 100644 --- a/include/AbstractState.h +++ b/include/AbstractState.h @@ -30,7 +30,8 @@ public: // everything is public, because IDGAF unsigned int Addr; unsigned int Unrolled; - bool Computed = false; + int Computed = 0; + bool Filled = false; // Only entries below this comment are needed for the exercise. @@ -164,6 +165,11 @@ public: // everything is public, because IDGAF * @param Addr , Address */ void update(Address Addr) { + // If Updated Address is of Age 0 do nothing + if (std::find(Sets[Addr.Index].Associativity[0].Blocks.begin(), + Sets[Addr.Index].Associativity[0].Blocks.end(), + Addr.Tag) != Sets[Addr.Index].Associativity[0].Blocks.end()) + return; // This loopages all entries by one. 3 <-2, 2<-1, 1<-0 for (int I = 3; I > 0; I--) { Sets[Addr.Index].Associativity[I] = Sets[Addr.Index].Associativity[I - 1]; @@ -173,27 +179,6 @@ public: // everything is public, because IDGAF Sets[Addr.Index].Associativity[0].Blocks = {Addr.Tag}; } - // /** - // * @brief Updates the AbstractState with given AbstractState - // * - // * @param UpdateState, State that gets merged into State with Age+1. - // */ - // void update(AbstractState UpdateState) { - // for (auto S : UpdateState.Sets) { - // unsigned int Index = S.first; - // for (auto E : S.second.Associativity) { - // unsigned int Age = E.first; - // // If updated age is greater 4 The Tag is no longer in Cache. - // // Due to associativity of 4 per set. - // if (Age >= 4) - // break; - // for (auto B : E.second.Blocks) { - // Sets[Index].Associativity[Age].Blocks.push_back(B); - // } - // } - // } - // } - /** * @brief Fills the AbstractState PreState and updates with PreAddress. * @@ -202,6 +187,7 @@ public: // everything is public, because IDGAF * @param PreAddr Address of PreState */ void fill(AbstractState PreState, Address PreAddr) { + bool Verbose = false; // copy Pre State into this. for (auto S : PreState.Sets) { unsigned int Index = S.first; @@ -216,13 +202,24 @@ public: // everything is public, because IDGAF } } } + if (Verbose) { + llvm::outs() << "Before:\n"; + this->dump(); + } // update this with PreAddr this->update(PreAddr); + if (Verbose) { + llvm::outs() << "Update Tag: " << PreAddr.Tag << "\n"; + llvm::outs() << "Update Set: " << PreAddr.Index << "\n"; + llvm::outs() << "After:\n"; + this->dump(); + } } void dump() { llvm::outs() << Addr << " {\n"; llvm::outs() << "Unrolled: " << Unrolled << "\n"; + llvm::outs() << "Computed: " << Computed << "\n"; llvm::outs() << "Predecessors: "; for (auto PreNr : Predecessors) { llvm::outs() << PreNr << " "; diff --git a/poolhelper.sh b/poolhelper.sh index d20d2a3..1bd33f3 100755 --- a/poolhelper.sh +++ b/poolhelper.sh @@ -145,29 +145,29 @@ case $1 in docker run -i -d -v "$(pwd)"/.:/root:rw --name RTSAlab01 rtsalab01cacheanalysis ;; evaluation | eval) - run "fft1" - echo "==== Correct fft1 ====" - echo "MustHits: 21" + run "crc" + echo "==== Correct crc ====" + echo "MustHits: 90" echo run "cnt" echo "==== Correct cnt ====" - echo "MustHits: 4" + echo "MustHits: 28" echo run "duff" echo "==== Correct duff ====" - echo "MustHits: 3" + echo "MustHits: 78" + echo + run "fft1" + echo "==== Correct fft1 ====" + echo "MustHits: 74" echo run "insertsort" echo "==== Correct insertsort ====" - echo "MustHits: 2" + echo "MustHits: 61" echo run "matmult" echo "==== Correct matmult ====" - echo "MustHits: 9" - echo - run "crc" - echo "==== Correct crc ====" - echo "MustHits: 6" + echo "MustHits: 34" echo ;; a | all)