forked from nils.hoelscher/RTSA-lab01-CacheAnalysis
Merge branch 'Fix-and-Loop-unrolling-'
This commit is contained in:
commit
1ae6af2eb6
|
@ -7,5 +7,6 @@ build/
|
||||||
.gnupg
|
.gnupg
|
||||||
.bash_history
|
.bash_history
|
||||||
.cache/
|
.cache/
|
||||||
|
*.solution
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
llvm/
|
llvm/
|
|
@ -4,6 +4,21 @@
|
||||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"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",
|
"type": "lldb",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
|
|
|
@ -46,52 +46,6 @@ using namespace llvm;
|
||||||
// everything in an anonymous namespace.
|
// everything in an anonymous namespace.
|
||||||
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
|
// New PM implementation
|
||||||
|
|
||||||
struct CacheAnalysisPass : PassInfoMixin<CacheAnalysisPass> {
|
struct CacheAnalysisPass : PassInfoMixin<CacheAnalysisPass> {
|
||||||
|
@ -102,6 +56,7 @@ struct CacheAnalysisPass : PassInfoMixin<CacheAnalysisPass> {
|
||||||
bool PrintEdgesPost = false;
|
bool PrintEdgesPost = false;
|
||||||
bool DumpToDot = false;
|
bool DumpToDot = false;
|
||||||
bool DumpNodes = false;
|
bool DumpNodes = false;
|
||||||
|
bool LoopUnrolling = true;
|
||||||
|
|
||||||
// Assume a 4kB Cache
|
// Assume a 4kB Cache
|
||||||
// with 16 Sets, associativity of 4 and Cachelines fitting two
|
// with 16 Sets, associativity of 4 and Cachelines fitting two
|
||||||
|
@ -274,15 +229,17 @@ struct CacheAnalysisPass : PassInfoMixin<CacheAnalysisPass> {
|
||||||
if (PrintAddresses)
|
if (PrintAddresses)
|
||||||
addressPrinter(F);
|
addressPrinter(F);
|
||||||
}
|
}
|
||||||
|
if(LoopUnrolling)
|
||||||
|
AC.unrollLoops();
|
||||||
|
AC.runMustAnalysis(EntryAddress);
|
||||||
|
if (DumpNodes)
|
||||||
|
AC.dumpNodes();
|
||||||
if (PrintEdgesPost)
|
if (PrintEdgesPost)
|
||||||
AC.dumpEdges();
|
AC.dumpEdges();
|
||||||
if (DumpToDot)
|
if (DumpToDot)
|
||||||
AC.dumpDotFile();
|
AC.dumpDotFile();
|
||||||
AC.fillAbstractCache(EntryAddress);
|
|
||||||
if (DumpNodes)
|
|
||||||
AC.dumpNodes();
|
|
||||||
outs() << "MustHits: " << AC.collectHits() << "\n";
|
outs() << "MustHits: " << AC.collectHits() << "\n";
|
||||||
outs() << "MayMisses: " << AC.collectMisses() << "\n";
|
//outs() << "MayMisses: " << AC.collectMisses() << "\n";
|
||||||
return PreservedAnalyses::all();
|
return PreservedAnalyses::all();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
67
helper.sh
67
helper.sh
|
@ -111,49 +111,30 @@ case $1 in
|
||||||
docker run -i -d -v "$(pwd)"/.:/root:rw --name RTSAlab01 rtsalab01cacheanalysis
|
docker run -i -d -v "$(pwd)"/.:/root:rw --name RTSAlab01 rtsalab01cacheanalysis
|
||||||
;;
|
;;
|
||||||
evaluation | eval)
|
evaluation | eval)
|
||||||
echo "Currently not available!"
|
run "crc"
|
||||||
echo "But please continue to implement the must join,"
|
echo "==== Correct crc ===="
|
||||||
echo "to the best of your abilities and check for updates!"
|
echo "MustHits: 90"
|
||||||
# run "fft1"
|
echo
|
||||||
# echo "==== Correct fft1 ===="
|
run "cnt"
|
||||||
# echo "MustHits: 16"
|
echo "==== Correct cnt ===="
|
||||||
# echo "MayMisses: 280"
|
echo "MustHits: 28"
|
||||||
# echo
|
echo
|
||||||
# run "bsort100"
|
run "duff"
|
||||||
# echo "==== Correct bsort100 ===="
|
echo "==== Correct duff ===="
|
||||||
# echo "MustHits: 1"
|
echo "MustHits: 78"
|
||||||
# echo "MayMisses: 41"
|
echo
|
||||||
# echo
|
run "fft1"
|
||||||
# run "lms"
|
echo "==== Correct fft1 ===="
|
||||||
# echo "==== Correct lms ===="
|
echo "MustHits: 74"
|
||||||
# echo "MustHits: 5"
|
echo
|
||||||
# echo "MayMisses: 288"
|
run "insertsort"
|
||||||
# echo
|
echo "==== Correct insertsort ===="
|
||||||
# run "minver"
|
echo "MustHits: 61"
|
||||||
# echo "==== Correct minver ===="
|
echo
|
||||||
# echo "MustHits: 6"
|
run "matmult"
|
||||||
# echo "MayMisses: 224"
|
echo "==== Correct matmult ===="
|
||||||
# echo
|
echo "MustHits: 34"
|
||||||
# run "qsort-exam"
|
echo
|
||||||
# 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
|
|
||||||
;;
|
;;
|
||||||
a | all)
|
a | all)
|
||||||
clean
|
clean
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
@ -44,51 +45,362 @@ public: // everything is public, because IDGAF
|
||||||
Nodes[Suc].Predecessors.push_back(Pre);
|
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;
|
* @brief Add an Empty node @NodeAddr
|
||||||
for (unsigned int SuccNr : Nodes[NodeNr].Successors) {
|
*
|
||||||
Nodes[SuccNr];
|
* @param NodeAddr
|
||||||
if (Nodes[SuccNr].Computed) {
|
* @return unsigned int
|
||||||
// Join don't call
|
*/
|
||||||
Nodes[SuccNr].mustJoin(Nodes[NodeNr]);
|
unsigned int addEmptyNode(unsigned int NodeAddr) {
|
||||||
Nodes[SuccNr].mustJoin(AbstractState(NodeNr));
|
int I = Nodes.size();
|
||||||
} else {
|
Nodes[I] = AbstractState(NodeAddr);
|
||||||
// Update and fill Succ
|
return I;
|
||||||
Nodes[SuccNr].fill(Nodes[NodeNr], NodeNr);
|
}
|
||||||
fillAbstractCache(SuccNr);
|
|
||||||
|
/**
|
||||||
|
* @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<unsigned int, bool> 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<unsigned int> LoopBodyIn,
|
||||||
|
std::map<unsigned int, unsigned int> 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<const unsigned int, AbstractState> 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<unsigned int> LoopBody;
|
||||||
|
std::list<unsigned int> 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<unsigned int, unsigned int> 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;
|
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 collectHits() {
|
||||||
unsigned int Hits = 0;
|
unsigned int Hits = 0;
|
||||||
for (auto const &E : Edges) {
|
for (auto const &E : Edges) {
|
||||||
auto Predecessor = Nodes[E.first];
|
auto Predecessor = Nodes[E.first];
|
||||||
for (unsigned int SuccessorAddr : E.second) {
|
for (unsigned int SuccessorAddr : E.second) {
|
||||||
// When successors Address is in predecessor, we have a Hit.
|
// 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;
|
return Hits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Return number of measured Misses
|
||||||
|
*
|
||||||
|
* @return unsigned int
|
||||||
|
*/
|
||||||
unsigned int collectMisses() {
|
unsigned int collectMisses() {
|
||||||
unsigned int Misses = 0;
|
unsigned int Misses = 0;
|
||||||
for (auto const &E : Edges) {
|
for (auto const &E : Edges) {
|
||||||
auto Predecessor = Nodes[E.first];
|
auto Predecessor = Nodes[E.first];
|
||||||
for (unsigned int SuccessorAddr : E.second) {
|
for (unsigned int SuccessorAddr : E.second) {
|
||||||
// When successors Address is in predecessor, we have a Hit.
|
// 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;
|
return Misses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Prints all Edges to Console
|
||||||
|
*
|
||||||
|
*/
|
||||||
void dumpEdges() {
|
void dumpEdges() {
|
||||||
llvm::outs() << "Dumping Edges:\n";
|
llvm::outs() << "Dumping Edges:\n";
|
||||||
for (auto const &E : Edges) {
|
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() {
|
void dumpDotFile() {
|
||||||
|
bool PrintOld = true;
|
||||||
std::ofstream DotFile;
|
std::ofstream DotFile;
|
||||||
DotFile.open("out.dot");
|
DotFile.open("out.dot");
|
||||||
DotFile << "digraph g {"
|
DotFile << "digraph g {"
|
||||||
<< "\n";
|
<< "\n";
|
||||||
for (auto const &E : Edges) {
|
for (auto const &E : Edges) {
|
||||||
for (unsigned int To : E.second) {
|
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 << "}\n";
|
||||||
DotFile.close();
|
DotFile.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Prints all nodes to Console
|
||||||
|
*
|
||||||
|
*/
|
||||||
void dumpNodes() {
|
void dumpNodes() {
|
||||||
for (auto const &E : Edges) {
|
for (auto const &E : Edges) {
|
||||||
Nodes[E.first].dump();
|
Nodes[E.first].dump();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef ABSSTATE_H
|
#ifndef ABSSTATE_H
|
||||||
#define ABSSTATE_H
|
#define ABSSTATE_H
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
@ -27,8 +28,10 @@ public: // everything is public, because IDGAF
|
||||||
std::list<unsigned int> Predecessors;
|
std::list<unsigned int> Predecessors;
|
||||||
|
|
||||||
unsigned int Addr;
|
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.
|
// Only entries below this comment are needed for the exercise.
|
||||||
|
|
||||||
|
@ -57,6 +60,8 @@ public: // everything is public, because IDGAF
|
||||||
std::map<unsigned int, Set> Sets;
|
std::map<unsigned int, Set> Sets;
|
||||||
|
|
||||||
AbstractState(AbstractState const &Copy) {
|
AbstractState(AbstractState const &Copy) {
|
||||||
|
Addr = Copy.Addr;
|
||||||
|
Unrolled = Copy.Unrolled;
|
||||||
for (auto S : Copy.Sets) {
|
for (auto S : Copy.Sets) {
|
||||||
unsigned int SetNr = S.first;
|
unsigned int SetNr = S.first;
|
||||||
for (auto E : S.second.Associativity) {
|
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() {}
|
||||||
|
|
||||||
AbstractState(unsigned int AddressIn) { Addr = AddressIn; }
|
AbstractState(unsigned int AddressIn) {
|
||||||
|
Addr = AddressIn;
|
||||||
|
Unrolled = 0;
|
||||||
|
}
|
||||||
|
|
||||||
AbstractState(Address Addr) {
|
AbstractState(unsigned int AddressIn, unsigned int UnrolledIn) {
|
||||||
Sets[Addr.Index].Associativity[0] = {{Addr.Tag}};
|
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
|
* @param Addr , Address
|
||||||
*/
|
*/
|
||||||
void update(Address Addr) {
|
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--) {
|
for (int I = 3; I > 0; I--) {
|
||||||
Sets[Addr.Index].Associativity[I] = Sets[Addr.Index].Associativity[I - 1];
|
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};
|
Sets[Addr.Index].Associativity[0].Blocks = {Addr.Tag};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Updates the AbstractState with given AbstractState
|
* @brief Fills the AbstractState PreState and updates with PreAddress.
|
||||||
*
|
|
||||||
* @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.
|
|
||||||
*
|
*
|
||||||
* @param PreState, State that fills this state.
|
* @param PreState, State that fills this state.
|
||||||
*
|
*
|
||||||
* @param PreAddr Address of PreState
|
* @param PreAddr Address of PreState
|
||||||
*/
|
*/
|
||||||
void fill(AbstractState PreState, Address PreAddr) {
|
void fill(AbstractState PreState, Address PreAddr) {
|
||||||
|
bool Verbose = false;
|
||||||
|
// copy Pre State into this.
|
||||||
for (auto S : PreState.Sets) {
|
for (auto S : PreState.Sets) {
|
||||||
unsigned int Index = S.first;
|
unsigned int Index = S.first;
|
||||||
for (auto E : S.second.Associativity) {
|
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.
|
// If updated age is greater 4 The Tag is no longer in Cache.
|
||||||
// Due to associativity of 4 per set.
|
// Due to associativity of 4 per set.
|
||||||
if (Age >= 4)
|
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() {
|
void dump() {
|
||||||
llvm::outs() << Addr << " {\n";
|
llvm::outs() << Addr << " {\n";
|
||||||
|
llvm::outs() << "Unrolled: " << Unrolled << "\n";
|
||||||
|
llvm::outs() << "Computed: " << Computed << "\n";
|
||||||
llvm::outs() << "Predecessors: ";
|
llvm::outs() << "Predecessors: ";
|
||||||
for (auto PreNr : Predecessors) {
|
for (auto PreNr : Predecessors) {
|
||||||
llvm::outs() << PreNr << " ";
|
llvm::outs() << PreNr << " ";
|
||||||
|
|
|
@ -145,49 +145,30 @@ case $1 in
|
||||||
docker run -i -d -v "$(pwd)"/.:/root:rw --name RTSAlab01 rtsalab01cacheanalysis
|
docker run -i -d -v "$(pwd)"/.:/root:rw --name RTSAlab01 rtsalab01cacheanalysis
|
||||||
;;
|
;;
|
||||||
evaluation | eval)
|
evaluation | eval)
|
||||||
echo "Currently not available!"
|
run "crc"
|
||||||
echo "But please continue to implement the must join,"
|
echo "==== Correct crc ===="
|
||||||
echo "to the best of your abilities and check for updates!"
|
echo "MustHits: 90"
|
||||||
# run "fft1"
|
echo
|
||||||
# echo "==== Correct fft1 ===="
|
run "cnt"
|
||||||
# echo "MustHits: 16"
|
echo "==== Correct cnt ===="
|
||||||
# echo "MayMisses: 280"
|
echo "MustHits: 28"
|
||||||
# echo
|
echo
|
||||||
# run "bsort100"
|
run "duff"
|
||||||
# echo "==== Correct bsort100 ===="
|
echo "==== Correct duff ===="
|
||||||
# echo "MustHits: 1"
|
echo "MustHits: 78"
|
||||||
# echo "MayMisses: 41"
|
echo
|
||||||
# echo
|
run "fft1"
|
||||||
# run "lms"
|
echo "==== Correct fft1 ===="
|
||||||
# echo "==== Correct lms ===="
|
echo "MustHits: 74"
|
||||||
# echo "MustHits: 5"
|
echo
|
||||||
# echo "MayMisses: 288"
|
run "insertsort"
|
||||||
# echo
|
echo "==== Correct insertsort ===="
|
||||||
# run "minver"
|
echo "MustHits: 61"
|
||||||
# echo "==== Correct minver ===="
|
echo
|
||||||
# echo "MustHits: 6"
|
run "matmult"
|
||||||
# echo "MayMisses: 224"
|
echo "==== Correct matmult ===="
|
||||||
# echo
|
echo "MustHits: 34"
|
||||||
# run "qsort-exam"
|
echo
|
||||||
# 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
|
|
||||||
;;
|
;;
|
||||||
a | all)
|
a | all)
|
||||||
clean
|
clean
|
||||||
|
|
Reference in New Issue