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/.vscode/launch.json b/.vscode/launch.json index e769ab8..aa8dcd9 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 Unrolling", + "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..97c4d2a 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 { @@ -102,6 +56,7 @@ struct CacheAnalysisPass : PassInfoMixin { bool PrintEdgesPost = false; bool DumpToDot = false; bool DumpNodes = false; + bool LoopUnrolling = true; // Assume a 4kB Cache // with 16 Sets, associativity of 4 and Cachelines fitting two @@ -274,15 +229,17 @@ struct CacheAnalysisPass : PassInfoMixin { if (PrintAddresses) addressPrinter(F); } + if(LoopUnrolling) + AC.unrollLoops(); + AC.runMustAnalysis(EntryAddress); + if (DumpNodes) + AC.dumpNodes(); if (PrintEdgesPost) AC.dumpEdges(); if (DumpToDot) AC.dumpDotFile(); - AC.fillAbstractCache(EntryAddress); - if (DumpNodes) - AC.dumpNodes(); 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 6693d95..c4138d6 100755 --- a/helper.sh +++ b/helper.sh @@ -111,49 +111,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 "crc" + echo "==== Correct crc ====" + echo "MustHits: 90" + echo + run "cnt" + echo "==== Correct cnt ====" + echo "MustHits: 28" + echo + run "duff" + echo "==== Correct duff ====" + echo "MustHits: 78" + echo + run "fft1" + echo "==== Correct fft1 ====" + echo "MustHits: 74" + echo + run "insertsort" + echo "==== Correct insertsort ====" + echo "MustHits: 61" + echo + run "matmult" + echo "==== Correct matmult ====" + echo "MustHits: 34" + echo ;; a | all) clean diff --git a/include/AbstractCache.h b/include/AbstractCache.h index f4b47e5..b4cf544 100644 --- a/include/AbstractCache.h +++ b/include/AbstractCache.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -44,51 +45,362 @@ public: // everything is public, because IDGAF Nodes[Suc].Predecessors.push_back(Pre); } - void addEmptyNode(unsigned int NodeAddr) { - Nodes[NodeAddr] = AbstractState(NodeAddr); + /** + * @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); } - void fillAbstractCache(unsigned int 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]); - Nodes[SuccNr].mustJoin(AbstractState(NodeNr)); - } else { - // Update and fill Succ - Nodes[SuccNr].fill(Nodes[NodeNr], NodeNr); - fillAbstractCache(SuccNr); + /** + * @brief Add an Empty node @NodeAddr + * + * @param NodeAddr + * @return unsigned int + */ + unsigned int addEmptyNode(unsigned int NodeAddr) { + 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]); + } + } + } + } + } + + /** + * @brief Unroll Loops. + * + * @param NodeNr + */ + void unrollLoops() { + 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 = false; + std::list LoopBody; + std::list AdditionalLoopTails; + 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 (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); + } else if (!FoundLoopBody) { + // If no coherent Loopbody exist we cannot unroll. + LoopBody.clear(); + IsLoopHead = false; + } + } + } + // Found Loop Head and Body! + // Add empty unrolled Nodes + // Map points from OrigNode To Unrolled Node. + 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); + } + + // 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"; + } } } return; } + /** + * @brief Perform must analysis in the Graph + * + * @param NodeNr + */ + void runMustAnalysis(unsigned int NodeNr) { + // Join and call until the state converges. + + 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 { + // 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; + } + + /** + * @brief Return number of measured Hits + * + * @return unsigned int + */ unsigned int collectHits() { unsigned int Hits = 0; for (auto const &E : Edges) { 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; } + /** + * @brief Return number of measured Misses + * + * @return unsigned int + */ unsigned int collectMisses() { unsigned int Misses = 0; for (auto const &E : Edges) { 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; } + /** + * @brief Prints all Edges to Console + * + */ void dumpEdges() { llvm::outs() << "Dumping Edges:\n"; for (auto const &E : Edges) { @@ -106,20 +418,38 @@ public: // everything is public, because IDGAF } } + /** + * @brief Dumps the Graph to a out.dot file + * + */ 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"; + 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 + << "\n"; + } } } DotFile << "}\n"; DotFile.close(); } + /** + * @brief Prints all nodes to Console + * + */ void dumpNodes() { for (auto const &E : Edges) { Nodes[E.first].dump(); diff --git a/include/AbstractState.h b/include/AbstractState.h index 3251353..46149d6 100644 --- a/include/AbstractState.h +++ b/include/AbstractState.h @@ -1,6 +1,7 @@ #ifndef ABSSTATE_H #define ABSSTATE_H +#include #include #include #include @@ -27,8 +28,10 @@ public: // everything is public, because IDGAF std::list Predecessors; 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. @@ -57,6 +60,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) { @@ -68,12 +73,61 @@ 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) { Addr = AddressIn; } + AbstractState(unsigned int AddressIn) { + Addr = AddressIn; + Unrolled = 0; + } - AbstractState(Address Addr) { - Sets[Addr.Index].Associativity[0] = {{Addr.Tag}}; + 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; } + + 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; } /** @@ -111,45 +165,34 @@ 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]; + 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 + 1; - // 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 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) { + bool Verbose = false; + // 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 +202,24 @@ public: // everything is public, because IDGAF } } } - Sets[PreAddr.Index].Associativity[0].Blocks.push_back(PreAddr.Tag); + 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 9918002..1bd33f3 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 "crc" + echo "==== Correct crc ====" + echo "MustHits: 90" + echo + run "cnt" + echo "==== Correct cnt ====" + echo "MustHits: 28" + echo + run "duff" + echo "==== Correct duff ====" + echo "MustHits: 78" + echo + run "fft1" + echo "==== Correct fft1 ====" + echo "MustHits: 74" + echo + run "insertsort" + echo "==== Correct insertsort ====" + echo "MustHits: 61" + echo + run "matmult" + echo "==== Correct matmult ====" + echo "MustHits: 34" + echo ;; a | all) clean