Compare commits

..

3 Commits

Author SHA1 Message Date
Nils Hölscher 8ea0c571e4 Added some simple UnitTests 2022-05-16 13:38:48 +02:00
Nils Hölscher 0d09aa9e45 Merge branch 'master' into UnitTest 2022-05-16 11:58:33 +02:00
Nils Hölscher 7635fb52c7 Removed dbg option for loopunrolling. 2022-05-16 11:58:20 +02:00
7 changed files with 241 additions and 65 deletions

30
.vscode/launch.json vendored
View File

@ -4,21 +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", // "type": "lldb",
"request": "launch", // "request": "launch",
"name": "LLDB Unrolling", // "name": "LLDB Unrolling",
"program": "/usr/bin/opt", // "program": "/usr/bin/opt",
"args": [ // "args": [
"-load-pass-plugin", // "-load-pass-plugin",
"${workspaceFolder}/build/libCacheAnalysisPass.so", // "${workspaceFolder}/build/libCacheAnalysisPass.so",
"-passes=lru-misses", // "-passes=lru-misses",
"${workspaceFolder}/test/cnt.ll", // "${workspaceFolder}/test/cnt.ll",
"-o", // "-o",
"/dev/null" // "/dev/null"
], // ],
"cwd": "${workspaceFolder}" // "cwd": "${workspaceFolder}"
}, // },
{ {
"type": "lldb", "type": "lldb",
"request": "launch", "request": "launch",

View File

@ -1,6 +1,19 @@
cmake_minimum_required(VERSION 3.13.4) cmake_minimum_required(VERSION 3.13.4)
project(RTSA-lab01-CacheAnalysis) project(RTSA-lab01-CacheAnalysis)
#===============================================================================
# 0. Add GoogleTest
#===============================================================================
include(FetchContent)
FetchContent_Declare(
googletest
URL
URL https://github.com/google/googletest/archive/05CC6081FCBD0071053DE78238E136B3.zip
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
#=============================================================================== #===============================================================================
# 1. VERIFY LLVM INSTALLATION DIR # 1. VERIFY LLVM INSTALLATION DIR
# This is just a bit of a sanity checking. # This is just a bit of a sanity checking.
@ -108,4 +121,5 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
# available for the sub-projects. # available for the sub-projects.
#=============================================================================== #===============================================================================
add_subdirectory(CacheAnalysisPass) # Use your pass name here. add_subdirectory(CacheAnalysisPass) # Use your pass name here.
add_subdirectory(UnitTest)
#add_subdirectory(lib) #add_subdirectory(lib)

52
UnitTest/CMakeLists.txt Normal file
View File

@ -0,0 +1,52 @@
cmake_minimum_required(VERSION 3.13.4)
project(UnitTest)
#===============================================================================
# 1. LOAD LLVM CONFIGURATION
#===============================================================================
# Set this to a valid LLVM installation dir
set(LT_LLVM_INSTALL_DIR "" CACHE PATH "LLVM installation directory")
# Add the location of LLVMConfig.cmake to CMake search paths (so that
# find_package can locate it)
list(APPEND CMAKE_PREFIX_PATH "${LT_LLVM_INSTALL_DIR}/lib/cmake/llvm/")
# FIXME: This is a warkaround for #25. Remove once resolved and use
# find_package(LLVM 11.0.0 REQUIRED CONFIG) instead.
find_package(LLVM REQUIRED CONFIG)
# UnitTest includes headers from LLVM - update the include paths accordingly
include_directories(SYSTEM ${LLVM_INCLUDE_DIRS}, "${CMAKE_CURRENT_SOURCE_DIR}/../include")
#===============================================================================
# 2. LLVM-TUTOR BUILD CONFIGURATION
#===============================================================================
# Use the same C++ standard as LLVM does
set(CMAKE_CXX_STANDARD 14 CACHE STRING "")
# LLVM is normally built without RTTI. Be consistent with that.
if(NOT LLVM_ENABLE_RTTI)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
endif()
#===============================================================================
# 3. ADD THE TARGET
#===============================================================================
enable_testing()
add_executable(UnitTest
# List your source files here.
UnitTest.cpp
)
# Allow undefined symbols in shared objects on Darwin (this is the default
# behaviour on Linux)
target_link_libraries(UnitTest
"$<$<PLATFORM_ID:Darwin>:-undefined dynamic_lookup>")
target_link_libraries(
UnitTest
gtest_main
)
include(GoogleTest)
gtest_discover_tests(UnitTest)

101
UnitTest/UnitTest.cpp Normal file
View File

@ -0,0 +1,101 @@
#include <gtest/gtest.h>
#include <sys/stat.h>
#include "../include/AbstractCache.h"
void fillSet(AbstractState &In, unsigned int Set) {
for (int I = 0; I < 4; I++) {
In.Sets[Set].Associativity[I].Blocks.push_front(I);
}
}
// Joined Set should remain the same
TEST(UnitTest, MustJoinSameStates) {
AbstractCache AC;
AC.addEmptyNode(0);
fillSet(AC.Nodes[0], 0);
AC.addEmptyNode(1);
fillSet(AC.Nodes[1], 0);
AC.Nodes[0].mustJoin(AC.Nodes[1]);
for (auto B : AC.Nodes[0].Sets[0].Associativity) {
uint Age = B.first;
EXPECT_EQ(AC.Nodes[0].Sets[0].Associativity[Age].Blocks.front(),
AC.Nodes[1].Sets[0].Associativity[Age].Blocks.front());
}
}
void counterFillSet(AbstractState &In, unsigned int Set) {
for (int I = 0; I < 4; I++) {
In.Sets[Set].Associativity[I].Blocks.push_front((I + 1) % 4);
}
}
// Resulting state should be
// Set[0]:
// Age[0]:
// Age[1]: 1
// Age[2]: 2
// Age[3]: 0 3
TEST(UnitTest, MustJoinDifferentStates) {
AbstractCache AC;
AC.addEmptyNode(0);
counterFillSet(AC.Nodes[0], 0);
AC.addEmptyNode(1);
fillSet(AC.Nodes[1], 0);
std::cout << "==Before:==\n";
AC.Nodes[0].dumpSet(0);
AC.Nodes[1].dumpSet(0);
AC.Nodes[0].mustJoin(AC.Nodes[1]);
std::cout << "\n==After:==\n";
AC.Nodes[0].dumpSet(0);
for (auto B : AC.Nodes[0].Sets[0].Associativity) {
uint Age = B.first;
switch (Age) {
case 0:
EXPECT_TRUE(AC.Nodes[0].Sets[0].Associativity[Age].Blocks.empty());
break;
case 1:
EXPECT_EQ(AC.Nodes[0].Sets[0].Associativity[Age].Blocks.front(), 1);
break;
case 2:
EXPECT_EQ(AC.Nodes[0].Sets[0].Associativity[Age].Blocks.front(), 2);
break;
case 3:
// this test is not very exact the Set 0 with age 3 should contain (0,3)
// in arbitrary order
EXPECT_EQ(AC.Nodes[0].Sets[0].Associativity[Age].Blocks.size(), 2);
break;
default:
// should never be reached!
EXPECT_TRUE(false);
}
}
}
void fillSetHighNumbers(AbstractState &In, unsigned int Set) {
for (int I = 0; I < 4; I++) {
In.Sets[Set].Associativity[I].Blocks.push_front(10+I);
}
}
// resulting state should be empty
TEST(UnitTest, MustJoinDisjunctStates) {
AbstractCache AC;
AC.addEmptyNode(0);
fillSetHighNumbers(AC.Nodes[0], 0);
AC.addEmptyNode(1);
fillSet(AC.Nodes[1], 0);
std::cout << "==Before:==\n";
AC.Nodes[0].dumpSet(0);
AC.Nodes[1].dumpSet(0);
AC.Nodes[0].mustJoin(AC.Nodes[1]);
std::cout << "\n==After:==\n";
AC.Nodes[0].dumpSet(0);
for (auto B : AC.Nodes[0].Sets[0].Associativity) {
uint Age = B.first;
EXPECT_TRUE(AC.Nodes[0].Sets[0].Associativity[Age].Blocks.empty());
}
}

View File

@ -11,7 +11,7 @@ config () {
mkdir build mkdir build
cd build cd build
echo "==== Configuring cmake ====" echo "==== Configuring cmake ===="
cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DLT_LLVM_INSTALL_DIR=$LLVM_DIR ../CacheAnalysisPass/ cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DLT_LLVM_INSTALL_DIR=/usr ..
cd .. cd ..
cp build/compile_commands.json compile_commands.json cp build/compile_commands.json compile_commands.json
echo "==== Done! ====" echo "==== Done! ===="

View File

@ -1,4 +1,3 @@
#ifndef ABSTRACHTCACHESTATE_H #ifndef ABSTRACHTCACHESTATE_H
#define ABSTRACHTCACHESTATE_H #define ABSTRACHTCACHESTATE_H
@ -11,9 +10,6 @@
#include <ostream> #include <ostream>
#include <utility> #include <utility>
#include <llvm/IR/BasicBlock.h>
#include <llvm/Support/raw_ostream.h>
#include "AbstractState.h" #include "AbstractState.h"
#include "Address.h" #include "Address.h"
#include "ConcreteState.h" #include "ConcreteState.h"
@ -292,34 +288,34 @@ public: // everything is public, because IDGAF
removeNestedLoops(LoopBody, OrigNodeToUnrolledNode); removeNestedLoops(LoopBody, OrigNodeToUnrolledNode);
if (Verbose && FoundLoopBody) { if (Verbose && FoundLoopBody) {
llvm::outs() << "Found LoopHead @: " << NodeNr << "\n"; std::cout << "Found LoopHead @: " << NodeNr << "\n";
llvm::outs() << "With LoopTail @: " << LoopTail << "\n"; std::cout << "With LoopTail @: " << LoopTail << "\n";
llvm::outs() << "With Body: {\n"; std::cout << "With Body: {\n";
int I = 1; int I = 1;
for (auto Node : LoopBody) { for (auto Node : LoopBody) {
llvm::outs() << Node << ", "; std::cout << Node << ", ";
if (!(I++ % 5)) { if (!(I++ % 5)) {
llvm::outs() << "\n"; std::cout << "\n";
} }
} }
llvm::outs() << "}\n"; std::cout << "}\n";
llvm::outs() << "Unrolled States: {\n"; std::cout << "Unrolled States: {\n";
I = 1; I = 1;
for (auto Node : LoopBody) { for (auto Node : LoopBody) {
llvm::outs() << OrigNodeToUnrolledNode[Node] << ", "; std::cout << OrigNodeToUnrolledNode[Node] << ", ";
if (!(I++ % 5)) { if (!(I++ % 5)) {
llvm::outs() << "\n"; std::cout << "\n";
} }
} }
llvm::outs() << "}\n"; std::cout << "}\n";
I = 1; I = 1;
llvm::outs() << "OrigNodeToUnrolledNode: {\n"; std::cout << "OrigNodeToUnrolledNode: {\n";
for (auto Nr : OrigNodeToUnrolledNode) { for (auto Nr : OrigNodeToUnrolledNode) {
llvm::outs() << Nr.first << "->" << Nr.second << ", "; std::cout << Nr.first << "->" << Nr.second << ", ";
if (!(I++ % 3)) if (!(I++ % 3))
llvm::outs() << "\n"; std::cout << "\n";
} }
llvm::outs() << "}\n"; std::cout << "}\n";
} }
} }
} }
@ -400,19 +396,19 @@ public: // everything is public, because IDGAF
* *
*/ */
void dumpEdges() { void dumpEdges() {
llvm::outs() << "Dumping Edges:\n"; std::cout << "Dumping Edges:\n";
for (auto const &E : Edges) { for (auto const &E : Edges) {
llvm::outs() << E.first; std::cout << E.first;
bool FirstPrint = true; bool FirstPrint = true;
for (unsigned int To : E.second) { for (unsigned int To : E.second) {
if (FirstPrint) { if (FirstPrint) {
llvm::outs() << " -> " << To; std::cout << " -> " << To;
FirstPrint = false; FirstPrint = false;
} else { } else {
llvm::outs() << ", " << To; std::cout << ", " << To;
} }
} }
llvm::outs() << "\n"; std::cout << "\n";
} }
} }
@ -453,5 +449,6 @@ public: // everything is public, because IDGAF
Nodes[E.first].dump(); Nodes[E.first].dump();
} }
} }
}; // namespace }; // namespace
#endif // ABSTRACHTCACHESTATE_H #endif // ABSTRACHTCACHESTATE_H

View File

@ -12,8 +12,6 @@
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <llvm/Support/raw_ostream.h>
#include "Address.h" #include "Address.h"
// Forward declarations // Forward declarations
@ -107,8 +105,8 @@ public: // everything is public, because IDGAF
void setUnrolled(unsigned int In) { Unrolled = In; } void setUnrolled(unsigned int In) { Unrolled = In; }
bool operator==(AbstractState In) { bool operator==(AbstractState In) {
for (int Index; Index < 16; Index++) { for (int Index = 0; Index < 16; Index++) {
for (int Age; Age < 4; Age++) { for (int Age = 0; Age < 4; Age++) {
for (auto E1 : Sets[Index].Associativity[Age].Blocks) { for (auto E1 : Sets[Index].Associativity[Age].Blocks) {
// find E1 in In States Set and Age. // find E1 in In States Set and Age.
if (std::find(In.Sets[Index].Associativity[Age].Blocks.begin(), if (std::find(In.Sets[Index].Associativity[Age].Blocks.begin(),
@ -203,46 +201,60 @@ public: // everything is public, because IDGAF
} }
} }
if (Verbose) { if (Verbose) {
llvm::outs() << "Before:\n"; std::cout << "Before:\n";
this->dump(); this->dump();
} }
// update this with PreAddr // update this with PreAddr
this->update(PreAddr); this->update(PreAddr);
if (Verbose) { if (Verbose) {
llvm::outs() << "Update Tag: " << PreAddr.Tag << "\n"; std::cout << "Update Tag: " << PreAddr.Tag << "\n";
llvm::outs() << "Update Set: " << PreAddr.Index << "\n"; std::cout << "Update Set: " << PreAddr.Index << "\n";
llvm::outs() << "After:\n"; std::cout << "After:\n";
this->dump(); this->dump();
} }
} }
void dump() { void dumpSet(unsigned int Set) {
llvm::outs() << Addr << " {\n"; std::cout << Addr << " {\n";
llvm::outs() << "Unrolled: " << Unrolled << "\n";
llvm::outs() << "Computed: " << Computed << "\n";
llvm::outs() << "Predecessors: ";
for (auto PreNr : Predecessors) {
llvm::outs() << PreNr << " ";
}
llvm::outs() << "\n";
llvm::outs() << "Successors: "; std::cout << "Set[" << Set << "]: \n";
for (auto SuccNr : Successors) { for (auto EntryPair : this->Sets[Set].Associativity) {
llvm::outs() << SuccNr << " "; std::cout << " Age[" << EntryPair.first << "]: ";
for (auto Block : EntryPair.second.Blocks) {
std::cout << Block << " ";
} }
llvm::outs() << "\n"; std::cout << "\n";
}
std::cout << "}\n";
}
void dump() {
std::cout << Addr << " {\n";
std::cout << "Unrolled: " << Unrolled << "\n";
std::cout << "Computed: " << Computed << "\n";
std::cout << "Predecessors: ";
for (auto PreNr : Predecessors) {
std::cout << PreNr << " ";
}
std::cout << "\n";
std::cout << "Successors: ";
for (auto SuccNr : Successors) {
std::cout << SuccNr << " ";
}
std::cout << "\n";
for (auto SetPair : Sets) { for (auto SetPair : Sets) {
llvm::outs() << "Set[" << SetPair.first << "]: \n"; std::cout << "Set[" << SetPair.first << "]: \n";
for (auto EntryPair : SetPair.second.Associativity) { for (auto EntryPair : SetPair.second.Associativity) {
llvm::outs() << " Age[" << EntryPair.first << "]: "; std::cout << " Age[" << EntryPair.first << "]: ";
for (auto Block : EntryPair.second.Blocks) { for (auto Block : EntryPair.second.Blocks) {
llvm::outs() << Block << " "; std::cout << Block << " ";
} }
llvm::outs() << "\n"; std::cout << "\n";
} }
} }
llvm::outs() << "}\n"; std::cout << "}\n";
} }
}; // namespace }; // namespace