From 87ece3ee6d9e349da794f0fd387dc9fdde9d437e Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Thu, 20 Jun 2024 16:26:44 +0200 Subject: [PATCH 001/105] cleanup: disabled detection of II_ dependencies --- rtlib/iFunctions.cpp | 305 ++---------------- rtlib/injected_functions/dp_decl.cpp | 2 +- rtlib/injected_functions/dp_read.cpp | 2 +- rtlib/injected_functions/dp_write.cpp | 2 +- share/lib/DPUtils.cpp | 7 - .../loops/loop_manager/test_loop_manager.cpp | 43 --- 6 files changed, 29 insertions(+), 332 deletions(-) diff --git a/rtlib/iFunctions.cpp b/rtlib/iFunctions.cpp index 2ebf3fc6a..0fe763d2a 100644 --- a/rtlib/iFunctions.cpp +++ b/rtlib/iFunctions.cpp @@ -70,268 +70,42 @@ void addDep(depType type, LID curr, LID depOn, const char *var, depType originalType = type; int loopIterationOffset = 0; - std::vector identifiedDepTypes; - bool dependencyRegistered = false; - // Compare metadata (Loop ID's and Loop Iterations) from LID's if loop id's - // are overwritten (not 0xFF anymore) and check for intra-iteration - // dependencies Intra-Iteration dependency exists, if LoopId's and Iteration - // Id's are equal - if (unpackLIDMetadata_getLoopID(curr) != (LID)0xFF && unpackLIDMetadata_getLoopID(depOn) != (LID)0xFF) { - if (unpackLIDMetadata_getLoopID(curr) == unpackLIDMetadata_getLoopID(depOn)) { - - // determine iteration count offset in case a new loop has been entered - // between curr and depOn - loopIterationOffset = - checkLIDMetadata_getLoopIterationValidity_0(curr) + checkLIDMetadata_getLoopIterationValidity_1(curr) + - checkLIDMetadata_getLoopIterationValidity_2(curr) - checkLIDMetadata_getLoopIterationValidity_0(depOn) - - checkLIDMetadata_getLoopIterationValidity_1(depOn) - checkLIDMetadata_getLoopIterationValidity_2(depOn); - - if (loopIterationOffset == 0) { - - if (checkLIDMetadata_getLoopIterationValidity_0(curr) && checkLIDMetadata_getLoopIterationValidity_0(depOn)) { - if (checkLIDMetadata_getLoopIterationValidity_1(curr) && checkLIDMetadata_getLoopIterationValidity_1(depOn)) { - if (checkLIDMetadata_getLoopIterationValidity_2(curr) && - checkLIDMetadata_getLoopIterationValidity_2(depOn)) { - // loop 0+1+2 valid - if (unpackLIDMetadata_getLoopIteration_2(curr) == unpackLIDMetadata_getLoopIteration_2(depOn)) { - identifiedDepTypes.push_back(II_2); - dependencyRegistered = true; - - if (unpackLIDMetadata_getLoopIteration_1(curr) == unpackLIDMetadata_getLoopIteration_1(depOn)) { - identifiedDepTypes.push_back(II_1); - if (unpackLIDMetadata_getLoopIteration_0(curr) == unpackLIDMetadata_getLoopIteration_0(depOn)) { - identifiedDepTypes.push_back(II_0); - } - } - } - } else { - // loop 0+1 valid - if (unpackLIDMetadata_getLoopIteration_1(curr) == unpackLIDMetadata_getLoopIteration_1(depOn)) { - identifiedDepTypes.push_back(II_1); - dependencyRegistered = true; - if (unpackLIDMetadata_getLoopIteration_0(curr) == unpackLIDMetadata_getLoopIteration_0(depOn)) { - identifiedDepTypes.push_back(II_0); - } - } - } - } else { - // loop 0 valid - if (unpackLIDMetadata_getLoopIteration_0(curr) == unpackLIDMetadata_getLoopIteration_0(depOn)) { - identifiedDepTypes.push_back(II_0); - dependencyRegistered = true; - } - } - } else { - // no loop valid - } - - } else if (loopIterationOffset == 1) { - // check outer loop - if ((unpackLIDMetadata_getLoopIteration_2(curr) == unpackLIDMetadata_getLoopIteration_1(depOn)) && - checkLIDMetadata_getLoopIterationValidity_2(curr) && checkLIDMetadata_getLoopIterationValidity_1(depOn)) { - // II 2 - identifiedDepTypes.push_back(II_2); - dependencyRegistered = true; - } - // check second loop - else if ((unpackLIDMetadata_getLoopIteration_1(curr) == unpackLIDMetadata_getLoopIteration_0(depOn)) && - checkLIDMetadata_getLoopIterationValidity_1(curr) && - checkLIDMetadata_getLoopIterationValidity_0(depOn)) { - // II 1 - identifiedDepTypes.push_back(II_1); - dependencyRegistered = true; - } - } else if (loopIterationOffset == 2) { - // check outer loop - if ((unpackLIDMetadata_getLoopIteration_2(curr) == unpackLIDMetadata_getLoopIteration_0(depOn)) && - checkLIDMetadata_getLoopIterationValidity_2(curr) && checkLIDMetadata_getLoopIterationValidity_0(depOn)) { - // II 2 - identifiedDepTypes.push_back(II_2); - dependencyRegistered = true; - } - } else if (loopIterationOffset == -2) { - // example: depOn inside an inner loop, curr happens after this inner - // loop - if ((unpackLIDMetadata_getLoopIteration_0(curr) == unpackLIDMetadata_getLoopIteration_2(depOn)) && - checkLIDMetadata_getLoopIterationValidity_0(curr) && checkLIDMetadata_getLoopIterationValidity_2(depOn)) { - // II 0 - identifiedDepTypes.push_back(II_0); - dependencyRegistered = true; - } - } else if (loopIterationOffset == -1) { - // check second loop - if ((unpackLIDMetadata_getLoopIteration_1(curr) == unpackLIDMetadata_getLoopIteration_2(depOn)) && - checkLIDMetadata_getLoopIterationValidity_1(curr) && checkLIDMetadata_getLoopIterationValidity_2(depOn)) { - // II 1 - identifiedDepTypes.push_back(II_1); - dependencyRegistered = true; - // check first loop - if ((unpackLIDMetadata_getLoopIteration_0(curr) == unpackLIDMetadata_getLoopIteration_1(depOn)) && - checkLIDMetadata_getLoopIterationValidity_0(curr) && checkLIDMetadata_getLoopIterationValidity_1(depOn)) { - // II 0 - identifiedDepTypes.push_back(II_0); - dependencyRegistered = true; - } - } - // check first loop - else { - if ((unpackLIDMetadata_getLoopIteration_0(curr) == unpackLIDMetadata_getLoopIteration_1(depOn)) && - checkLIDMetadata_getLoopIterationValidity_0(curr) && checkLIDMetadata_getLoopIterationValidity_1(depOn)) { - // II 0 - identifiedDepTypes.push_back(II_0); - dependencyRegistered = true; - } - } - } - } - } + // Remove metadata to preserve result correctness and add metadata to `Dep` + // object - if (!dependencyRegistered) { - // register dependency with original type - identifiedDepTypes.push_back(NOM); + // register dependency + depMap::iterator posInDeps = myMap->find(curr); + if (posInDeps == myMap->end()) { + depSet *tmp_depSet = new depSet(); + tmp_depSet->insert(Dep(type, depOn, var, AAvar)); + myMap->insert(std::pair(curr, tmp_depSet)); + } else { + posInDeps->second->insert(Dep(type, depOn, var, AAvar)); } - // Remove metadata to preserve result correctness and add metadata to `Dep` - // object - LID dbg_curr = curr; // for printing only - LID dbg_depOn = depOn; // for printing only - - curr &= 0x00000000FFFFFFFF; - depOn &= 0x00000000FFFFFFFF; - - std::vector> dependenciesToBeRegistered; - dependenciesToBeRegistered.reserve(identifiedDepTypes.size()); - - for (depTypeModifier dtm : identifiedDepTypes) { - depType modified_type = type; - bool print_debug_info = false; - switch (dtm) { - case NOM: - // keep modified_type = type - // print_debug_info = true; + if (DP_DEBUG) { + cout << "inserted dep [" << decodeLID(curr) << ", "; + switch (type) { + case RAW: + cout << "RAW"; + break; + case WAR: + cout << "WAR"; + break; + case WAW: + cout << "WAW"; + break; + case INIT: + cout << "INIT"; break; - case II_0: { - switch (type) { - case RAW: - modified_type = RAW_II_0; - break; - case WAR: - modified_type = WAR_II_0; - break; - case WAW: - modified_type = WAW_II_0; - break; - case INIT: - break; - default: - break; - } - } break; - case II_1: { - switch (type) { - case RAW: - modified_type = RAW_II_1; - break; - case WAR: - modified_type = WAR_II_1; - break; - case WAW: - modified_type = WAW_II_1; - break; - case INIT: - break; - default: - break; - } - } break; - case II_2: { - switch (type) { - case RAW: - modified_type = RAW_II_2; - break; - case WAR: - modified_type = WAR_II_2; - break; - case WAW: - modified_type = WAW_II_2; - break; - case INIT: - break; - default: - break; - } - } break; default: break; } - - if (isStackAccess && (modified_type == WAR || modified_type == RAW || modified_type == WAW) && - addrIsFirstWrittenInScope && positiveScopeChangeOccuredSinceLastAccess) { - // IGNORE ACCESS - } else { - // register dependency - // depType T, LID dep, char *var, std::string AAvar, std::set iaid, - // std::set ieid, std::set iacd, std::set iecd - dependenciesToBeRegistered.emplace_back(Dep(modified_type, depOn, var, AAvar), - curr); - } - - if (print_debug_info) { - cout << "AddDep: CURR: " << decodeLID(curr) << " DepOn: " << decodeLID(dbg_depOn) << " LoopIDS: " << hex - << unpackLIDMetadata_getLoopID(dbg_curr) << ";" << hex << unpackLIDMetadata_getLoopID(dbg_depOn) << "\n"; - cout << " Var: " << var << "\n"; - cout << " Loop Iterations(curr): " << hex << unpackLIDMetadata_getLoopIteration_0(dbg_curr) << ";" << hex - << unpackLIDMetadata_getLoopIteration_1(dbg_curr) << ";" << hex - << unpackLIDMetadata_getLoopIteration_2(dbg_curr) << "\n"; - cout << " Loop Iterations(depOn): " << hex << unpackLIDMetadata_getLoopIteration_0(dbg_depOn) << ";" << hex - << unpackLIDMetadata_getLoopIteration_1(dbg_depOn) << ";" << hex - << unpackLIDMetadata_getLoopIteration_2(dbg_depOn) << "\n"; - cout << " Valid(cur): " << checkLIDMetadata_getLoopIterationValidity_0(dbg_curr) << ";" - << checkLIDMetadata_getLoopIterationValidity_1(dbg_curr) << ";" - << checkLIDMetadata_getLoopIterationValidity_2(dbg_curr) << ";\n"; - cout << " Valid(dep): " << checkLIDMetadata_getLoopIterationValidity_0(dbg_depOn) << ";" - << checkLIDMetadata_getLoopIterationValidity_1(dbg_depOn) << ";" - << checkLIDMetadata_getLoopIterationValidity_2(dbg_depOn) << ";\n"; - cout << " LoopIterationOffset: " << to_string(loopIterationOffset) << "\n"; - cout << " orig.type: " << originalType << "\n"; - cout << " final.type: " << modified_type << "\n\n"; - } - } - - // register dependencies - for (std::pair pair : dependenciesToBeRegistered) { - depMap::iterator posInDeps = myMap->find(pair.second); - if (posInDeps == myMap->end()) { - depSet *tmp_depSet = new depSet(); - tmp_depSet->insert(Dep(pair.first.type, pair.first.depOn, pair.first.var, pair.first.AAvar)); - myMap->insert(std::pair(pair.second, tmp_depSet)); - } else { - posInDeps->second->insert(Dep(pair.first.type, pair.first.depOn, pair.first.var, pair.first.AAvar)); - } - - if (DP_DEBUG) { - cout << "inserted dep [" << decodeLID(pair.second) << ", "; - switch (type) { - case RAW: - cout << "RAW"; - break; - case WAR: - cout << "WAR"; - break; - case WAW: - cout << "WAW"; - break; - case INIT: - cout << "INIT"; - break; - default: - break; - } - cout << ", " << decodeLID(pair.first.depOn) << "] into deps (" << myMap->size() << ")" << endl; - } + cout << ", " << decodeLID(depOn) << "] into deps (" << myMap->size() << ")" << endl; } } + // hybrid analysis void generateStringDepMap() { #ifdef DP_RTLIB_VERBOSE @@ -357,33 +131,6 @@ void generateStringDepMap() { case WAW: dep += "WAW"; break; - case RAW_II_0: - dep += "RAW_II_0"; - break; - case WAR_II_0: - dep += "WAR_II_0"; - break; - case WAW_II_0: - dep += "WAW_II_0"; - break; - case RAW_II_1: - dep += "RAW_II_1"; - break; - case WAR_II_1: - dep += "WAR_II_1"; - break; - case WAW_II_1: - dep += "WAW_II_1"; - break; - case RAW_II_2: - dep += "RAW_II_2"; - break; - case WAR_II_2: - dep += "WAR_II_2"; - break; - case WAW_II_2: - dep += "WAW_II_2"; - break; case INIT: dep += "INIT"; break; diff --git a/rtlib/injected_functions/dp_decl.cpp b/rtlib/injected_functions/dp_decl.cpp index 59a52ff00..deff35605 100644 --- a/rtlib/injected_functions/dp_decl.cpp +++ b/rtlib/injected_functions/dp_decl.cpp @@ -75,7 +75,7 @@ void __dp_decl(LID lid, ADDR addr, char *var) { int64_t workerID = ((addr - (addr % 4)) % (NUM_WORKERS * 4)) / 4; // implicit "floor" AccessInfo ¤t = tempAddrChunks[workerID][tempAddrCount[workerID]++]; current.isRead = false; - current.lid = loop_manager->update_lid(0); + current.lid = 0; current.var = var; current.AAvar = getMemoryRegionIdFromAddr(var, addr); current.addr = addr; diff --git a/rtlib/injected_functions/dp_read.cpp b/rtlib/injected_functions/dp_read.cpp index 290fcf992..d8c7b91d4 100644 --- a/rtlib/injected_functions/dp_read.cpp +++ b/rtlib/injected_functions/dp_read.cpp @@ -86,7 +86,7 @@ void __dp_read(LID lid, ADDR addr, const char *var) { AccessInfo ¤t = tempAddrChunks[workerID][tempAddrCount[workerID]++]; #endif current.isRead = true; - current.lid = loop_manager->update_lid(lid); + current.lid = lid; current.var = var; current.AAvar = getMemoryRegionIdFromAddr(var, addr); current.addr = addr; diff --git a/rtlib/injected_functions/dp_write.cpp b/rtlib/injected_functions/dp_write.cpp index 040d3e29d..9881b733d 100644 --- a/rtlib/injected_functions/dp_write.cpp +++ b/rtlib/injected_functions/dp_write.cpp @@ -88,7 +88,7 @@ void __dp_write(LID lid, ADDR addr, const char *var) { AccessInfo ¤t = tempAddrChunks[workerID][tempAddrCount[workerID]++]; #endif current.isRead = false; - current.lid = loop_manager->update_lid(lid); + current.lid = lid; current.var = var; current.AAvar = getMemoryRegionIdFromAddr(var, addr); current.addr = addr; diff --git a/share/lib/DPUtils.cpp b/share/lib/DPUtils.cpp index 9aa7771a3..98090172e 100644 --- a/share/lib/DPUtils.cpp +++ b/share/lib/DPUtils.cpp @@ -154,13 +154,6 @@ int64_t getLID(Instruction *BI, int32_t &fileID) { } lid = (fileID << LIDSIZE) + lno; - // get and store metadata in the first 32 Bits if necessary - // Layout metadata: - // 8 bits reserved for loop id (added dynamically) - // 8 bits reserved for loop iteration (added dynamically) - // 16 bits unused - // initialize loop id - return lid; } diff --git a/test/unit_tests/loops/loop_manager/test_loop_manager.cpp b/test/unit_tests/loops/loop_manager/test_loop_manager.cpp index db6734885..65fcc7868 100644 --- a/test/unit_tests/loops/loop_manager/test_loop_manager.cpp +++ b/test/unit_tests/loops/loop_manager/test_loop_manager.cpp @@ -23,9 +23,6 @@ TEST_F(LoopManagerTest, testInitialization) { for (auto i = 0; i < 100; i++) { ASSERT_TRUE(lm.is_single_exit(i)); } - - const auto lid = (LID)0; - ASSERT_EQ(lm.update_lid(lid), 0xFF00000000000000LL); } TEST_F(LoopManagerTest, testCreateNewLoop) { @@ -114,46 +111,6 @@ TEST_F(LoopManagerTest, testCleanFunctionExit) { ASSERT_EQ(loop->total, 0); } -TEST_F(LoopManagerTest, testUpdateLid) { - auto lm = __dp::LoopManager(); - - const auto &table = lm.get_stack(); - const auto &loops = lm.get_loops(); - - lm.create_new_loop(1, 2, 0); - lm.create_new_loop(4, 5, 0); - lm.create_new_loop(7, 8, 0); - lm.create_new_loop(10, 11, 0); - lm.create_new_loop(13, 14, 0); - - const auto lid_1 = 0b0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000LL; - const auto lid_2 = 0b1111'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000LL; - const auto lid_3 = 0b0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'1111LL; - const auto lid_4 = 0b0000'1111'0000'1111'0000'1111'0000'1111'0000'1111'0000'1111'0000'1111'0000'1111LL; - const auto lid_5 = 0b1111'0000'1111'0000'1111'0000'1111'0000'1111'0000'1111'0000'1111'0000'1111'0000LL; - const auto lid_6 = 0b0000'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111LL; - const auto lid_7 = 0b1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'0000LL; - const auto lid_8 = 0b1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111LL; - - const auto expected_lid_1 = table.update_lid(lid_1); - const auto expected_lid_2 = table.update_lid(lid_2); - const auto expected_lid_3 = table.update_lid(lid_3); - const auto expected_lid_4 = table.update_lid(lid_4); - const auto expected_lid_5 = table.update_lid(lid_5); - const auto expected_lid_6 = table.update_lid(lid_6); - const auto expected_lid_7 = table.update_lid(lid_7); - const auto expected_lid_8 = table.update_lid(lid_8); - - ASSERT_EQ(expected_lid_1, lm.update_lid(lid_1)); - ASSERT_EQ(expected_lid_2, lm.update_lid(lid_2)); - ASSERT_EQ(expected_lid_3, lm.update_lid(lid_3)); - ASSERT_EQ(expected_lid_4, lm.update_lid(lid_4)); - ASSERT_EQ(expected_lid_5, lm.update_lid(lid_5)); - ASSERT_EQ(expected_lid_6, lm.update_lid(lid_6)); - ASSERT_EQ(expected_lid_7, lm.update_lid(lid_7)); - ASSERT_EQ(expected_lid_8, lm.update_lid(lid_8)); -} - TEST_F(LoopManagerTest, testExitLoop) { auto lm = __dp::LoopManager(); From 17faf3b1980afa8d36c2252d10fe93aed6062cc0 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Thu, 20 Jun 2024 16:38:55 +0200 Subject: [PATCH 002/105] cleanup: remove Memory dealiasing and stack detection --- CMakeLists.txt | 2 -- docs/setup/discopop.md | 2 -- rtlib/CMakeLists.txt | 14 -------------- rtlib/iFunctions.cpp | 19 +++++++++---------- rtlib/iFunctionsTypes.hpp | 3 --- rtlib/injected_functions/dp_read.cpp | 11 ----------- rtlib/injected_functions/dp_write.cpp | 12 ------------ 7 files changed, 9 insertions(+), 54 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cb87fc99c..ab00d41f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -93,8 +93,6 @@ file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build_config.py" "DP_RTLIB_VERBOSE=\"${DP_RTLIB_VERBOSE}\"\n") file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build_config.py" "DP_NUM_WORKERS=\"${DP_NUM_WORKERS}\"\n") file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build_config.py" "DP_INTERNAL_TIMER=\"${DP_INTERNAL_TIMER}\"\n") -file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build_config.py" "DP_MEMORY_REGION_DEALIASING=\"${DP_MEMORY_REGION_DEALIASING}\"\n") -file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build_config.py" "DP_STACK_ACCESS_DETECTION=\"${DP_STACK_ACCESS_DETECTION}\"\n") # print DiscoPoP configuration file(READ ${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build_config.py DiscoPoP_CONFIGURATION) diff --git a/docs/setup/discopop.md b/docs/setup/discopop.md index 1eff4b002..d9208a088 100644 --- a/docs/setup/discopop.md +++ b/docs/setup/discopop.md @@ -33,8 +33,6 @@ where `` can consist of any combination of the following flags and - `-DDP_PTHREAD_COMPATIBILITY_MODE=[0|1]` – If your application uses PThreads, please specify this flag to serialize the calls to the DiscoPoP runtime functions. Note, however, that this can negatively influence the runtime of the profiling. - `-DDP_NUM_WORKERS=` – Specify the number of worker threads available for the dependency analysis during profiling. Default: `3` worker threads. `0` can be used to disable the creation of additional threads for the analysis. - `-DDP_HYBRID_PROFILING=[0|1]` – Enbale hybrid profiling. Default: `1`. -- `-DDP_MEMORY_REGION_DEALIASING=[0|1]`: Enable or disable the generation of dependency de-aliasing information. Reduces potential false positive parallelization suggestions, but increases the profiling overhead. -- `-DDP_STACK_ACCESS_DETECTION=[0|1]`: Enable or disable stack dependency detection. Enabling will reduce false positive dependences, but increase the profiling overhead. This flag only has an effect on the results, if `-DDP_HYBRID_PROFILING=0`. #### Development and debugging - `-DDP_RTLIB_VERBOSE=[0|1]` – Enable verbose output during profiling. diff --git a/rtlib/CMakeLists.txt b/rtlib/CMakeLists.txt index 5996a1b59..30cca649f 100644 --- a/rtlib/CMakeLists.txt +++ b/rtlib/CMakeLists.txt @@ -72,20 +72,6 @@ if(DEFINED DP_INTERNAL_TIMER) endif() endif() -if(DEFINED DP_MEMORY_REGION_DEALIASING) - if(NOT ${DP_MEMORY_REGION_DEALIASING} EQUAL 0) - target_compile_definitions(DiscoPoP_RT PUBLIC DP_MEMORY_REGION_DEALIASING=${DP_MEMORY_REGION_DEALIASING}) - message(STATUS "WARNING: DiscoPoP configuration: DP_MEMORY_REGION_DEALIASING enabled. Reduces profiling speed.") - endif() -endif() - -if(DEFINED DP_STACK_ACCESS_DETECTION) - if(NOT ${DP_STACK_ACCESS_DETECTION} EQUAL 0) - target_compile_definitions(DiscoPoP_RT PUBLIC DP_STACK_ACCESS_DETECTION=${DP_STACK_ACCESS_DETECTION}) - message(STATUS "WARNING: DiscoPoP configuration: DP_STACK_ACCESS_DETECTION enabled. Reduces profiling speed.") - endif() -endif() - # end of compiler flags install(TARGETS DiscoPoP_RT ARCHIVE DESTINATION lib) diff --git a/rtlib/iFunctions.cpp b/rtlib/iFunctions.cpp index 0fe763d2a..14dad89ff 100644 --- a/rtlib/iFunctions.cpp +++ b/rtlib/iFunctions.cpp @@ -56,8 +56,7 @@ namespace __dp { /******* Helper functions *******/ void addDep(depType type, LID curr, LID depOn, const char *var, - string AAvar, bool isStackAccess, ADDR addr, bool addrIsFirstWrittenInScope, - bool positiveScopeChangeOccuredSinceLastAccess) { + string AAvar, ADDR addr) { #ifdef DP_INTERNAL_TIMER const auto timer = Timer(timers, TimerRegion::ADD_DEP); #endif @@ -343,28 +342,28 @@ void analyzeSingleAccess(__dp::AbstractShadow *SMem, __dp::AccessInfo &access) { if (lastWrite != 0) { // RAW SMem->insertToRead(access.addr, access.lid); - addDep(RAW, access.lid, lastWrite, access.var, access.AAvar, access.isStackAccess, - access.addr, access.addrIsOwnedByScope, access.positiveScopeChangeOccuredSinceLastAccess); + addDep(RAW, access.lid, lastWrite, access.var, access.AAvar, + access.addr); } } else { sigElement lastWrite = SMem->insertToWrite(access.addr, access.lid); if (lastWrite == 0) { // INIT - addDep(INIT, access.lid, 0, access.var, access.AAvar, access.isStackAccess, - access.addr, access.addrIsOwnedByScope, access.positiveScopeChangeOccuredSinceLastAccess); + addDep(INIT, access.lid, 0, access.var, access.AAvar, + access.addr); } else { sigElement lastRead = SMem->testInRead(access.addr); if (lastRead != 0) { // WAR - addDep(WAR, access.lid, lastRead, access.var, access.AAvar, access.isStackAccess, - access.addr, access.addrIsOwnedByScope, access.positiveScopeChangeOccuredSinceLastAccess); + addDep(WAR, access.lid, lastRead, access.var, access.AAvar, + access.addr); // Clear intermediate read ops SMem->insertToRead(access.addr, 0); } else { // WAW - addDep(WAW, access.lid, lastWrite, access.var, access.AAvar, access.isStackAccess, - access.addr, access.addrIsOwnedByScope, access.positiveScopeChangeOccuredSinceLastAccess); + addDep(WAW, access.lid, lastWrite, access.var, access.AAvar, + access.addr); } } } diff --git a/rtlib/iFunctionsTypes.hpp b/rtlib/iFunctionsTypes.hpp index 1395dbf86..34234310e 100644 --- a/rtlib/iFunctionsTypes.hpp +++ b/rtlib/iFunctionsTypes.hpp @@ -66,9 +66,6 @@ struct AccessInfo { const char *var; std::string AAvar; // name of allocated variable -> "Anti Aliased Variable" ADDR addr; - bool isStackAccess = false; - bool addrIsOwnedByScope = false; - bool positiveScopeChangeOccuredSinceLastAccess = false; }; // For runtime dependency merging diff --git a/rtlib/injected_functions/dp_read.cpp b/rtlib/injected_functions/dp_read.cpp index d8c7b91d4..2bc02b643 100644 --- a/rtlib/injected_functions/dp_read.cpp +++ b/rtlib/injected_functions/dp_read.cpp @@ -91,17 +91,6 @@ void __dp_read(LID lid, ADDR addr, const char *var) { current.AAvar = getMemoryRegionIdFromAddr(var, addr); current.addr = addr; -#if DP_STACK_ACCESS_DETECTION - current.isStackAccess = is_stack_access; - current.addrIsOwnedByScope = memory_manager->isFirstWrittenInScope(addr, false); - current.positiveScopeChangeOccuredSinceLastAccess = memory_manager->positiveScopeChangeOccuredSinceLastAccess(addr); - if (is_stack_access) { - // register stack read after check for - // positiveScopeChangeOccuredSinceLastAccess - memory_manager->registerStackRead(addr, lid, var); - } -#endif - #if defined DP_NUM_WORKERS && DP_NUM_WORKERS == 0 analyzeSingleAccess(singleThreadedExecutionSMem, current); #else diff --git a/rtlib/injected_functions/dp_write.cpp b/rtlib/injected_functions/dp_write.cpp index 9881b733d..bb9298670 100644 --- a/rtlib/injected_functions/dp_write.cpp +++ b/rtlib/injected_functions/dp_write.cpp @@ -93,18 +93,6 @@ void __dp_write(LID lid, ADDR addr, const char *var) { current.AAvar = getMemoryRegionIdFromAddr(var, addr); current.addr = addr; -#if DP_STACK_ACCESS_DETECTION - current.isStackAccess = is_stack_access; - current.addrIsOwnedByScope = memory_manager->isFirstWrittenInScope(addr, true); - current.positiveScopeChangeOccuredSinceLastAccess = memory_manager->positiveScopeChangeOccuredSinceLastAccess(addr); - - if (is_stack_access) { - // register stack write after check for - // positiveScopeChangeOccuredSinceLastAccess - memory_manager->registerStackWrite(addr, lid, var); - } -#endif - #if defined DP_NUM_WORKERS && DP_NUM_WORKERS == 0 analyzeSingleAccess(singleThreadedExecutionSMem, current); #else From 1fb1654b6f009041700da804d24e3d42f42f3bdc Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 2 Jul 2024 08:12:45 +0200 Subject: [PATCH 003/105] feat[profiler,explorer]: add calltree profiling and dependency metadata chore: add license tags fix: add boost to ci setup fix: enabled calltree profiling in CI tests doc: add warning to reduction detection --- .github/workflows/ci.yml | 12 +- CMakeLists.txt | 6 + discopop_explorer/PEGraphX.py | 47 ++--- discopop_explorer/parser.py | 45 ++++- .../pattern_detectors/do_all_detector.py | 96 ++++++++++- .../pattern_detectors/reduction_detector.py | 110 +++++++++++- docs/setup/discopop.md | 3 + rtlib/CMakeLists.txt | 23 +++ rtlib/calltree/CallTree.cpp | 94 ++++++++++ rtlib/calltree/CallTree.hpp | 42 +++++ rtlib/calltree/CallTreeGlobals.cpp | 15 ++ rtlib/calltree/CallTreeGlobals.hpp | 17 ++ rtlib/calltree/CallTreeNode.cpp | 74 ++++++++ rtlib/calltree/CallTreeNode.hpp | 41 +++++ rtlib/calltree/CallTreeNodeType.hpp | 24 +++ rtlib/calltree/DependencyMetadata.cpp | 91 ++++++++++ rtlib/calltree/DependencyMetadata.hpp | 71 ++++++++ rtlib/calltree/MetaDataQueue.cpp | 139 +++++++++++++++ rtlib/calltree/MetaDataQueue.hpp | 54 ++++++ rtlib/calltree/MetaDataQueueElement.cpp | 55 ++++++ rtlib/calltree/MetaDataQueueElement.hpp | 67 ++++++++ rtlib/calltree/utils.cpp | 156 +++++++++++++++++ rtlib/calltree/utils.hpp | 18 ++ rtlib/iFunctions.cpp | 122 ++++++++++++- rtlib/iFunctionsGlobals.cpp | 4 + rtlib/iFunctionsGlobals.hpp | 6 + rtlib/iFunctionsTypes.hpp | 21 ++- rtlib/injected_functions/dp_alloca.cpp | 4 + rtlib/injected_functions/dp_finalize.cpp | 29 ++++ rtlib/injected_functions/dp_func_entry.cpp | 11 ++ rtlib/injected_functions/dp_func_exit.cpp | 4 + rtlib/injected_functions/dp_loop_entry.cpp | 9 + rtlib/injected_functions/dp_loop_exit.cpp | 4 + rtlib/injected_functions/dp_read.cpp | 3 + rtlib/injected_functions/dp_write.cpp | 4 + share/include/timer.hpp | 25 ++- .../do_all/calls/complex/src/code.cpp | 2 +- .../complex_no_varname_duplicates/__init__.py | 0 .../src/Makefile | 17 ++ .../src/code.cpp | 40 +++++ .../complex_no_varname_duplicates/test.py | 74 ++++++++ test/unit_tests/CMakeLists.txt | 5 +- .../calltree/call_tree/test_call_tree.cpp | 162 ++++++++++++++++++ .../call_tree_node/test_call_tree_node.cpp | 74 ++++++++ .../metadata_queue/test_metadata_queue.cpp | 8 + 45 files changed, 1878 insertions(+), 50 deletions(-) create mode 100644 rtlib/calltree/CallTree.cpp create mode 100644 rtlib/calltree/CallTree.hpp create mode 100644 rtlib/calltree/CallTreeGlobals.cpp create mode 100644 rtlib/calltree/CallTreeGlobals.hpp create mode 100644 rtlib/calltree/CallTreeNode.cpp create mode 100644 rtlib/calltree/CallTreeNode.hpp create mode 100644 rtlib/calltree/CallTreeNodeType.hpp create mode 100644 rtlib/calltree/DependencyMetadata.cpp create mode 100644 rtlib/calltree/DependencyMetadata.hpp create mode 100644 rtlib/calltree/MetaDataQueue.cpp create mode 100644 rtlib/calltree/MetaDataQueue.hpp create mode 100644 rtlib/calltree/MetaDataQueueElement.cpp create mode 100644 rtlib/calltree/MetaDataQueueElement.hpp create mode 100644 rtlib/calltree/utils.cpp create mode 100644 rtlib/calltree/utils.hpp create mode 100644 test/end_to_end/do_all/calls/complex_no_varname_duplicates/__init__.py create mode 100644 test/end_to_end/do_all/calls/complex_no_varname_duplicates/src/Makefile create mode 100644 test/end_to_end/do_all/calls/complex_no_varname_duplicates/src/code.cpp create mode 100644 test/end_to_end/do_all/calls/complex_no_varname_duplicates/test.py create mode 100644 test/unit_tests/calltree/call_tree/test_call_tree.cpp create mode 100644 test/unit_tests/calltree/call_tree_node/test_call_tree_node.cpp create mode 100644 test/unit_tests/calltree/metadata_queue/test_metadata_queue.cpp diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a50c85227..a1227385f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -95,13 +95,17 @@ jobs: sudo ln -s /usr/bin/llvm-link-11 /usr/bin/llvm-link || true sudo ln -s /usr/bin/opt-11 /usr/bin/opt || true sudo apt-get install -y python3-tk + sudo apt-get install -y libboost-all-dev - name: "Setup DiscoPoP Profiler - Build" run: | rm -rf build mkdir build cd build - cmake -DCMAKE_BUILD_TYPE=Debug .. + cmake \ + -DCMAKE_BUILD_TYPE=Debug \ + -DDP_CALLTREE_PROFILING=1 \ + .. make -j3 - name: C++ unit tests @@ -138,13 +142,17 @@ jobs: sudo ln -s /usr/bin/llvm-link-11 /usr/bin/llvm-link || true sudo ln -s /usr/bin/opt-11 /usr/bin/opt || true sudo apt-get install -y python3-tk + sudo apt-get install -y libboost-all-dev - name: "Setup DiscoPoP Profiler - Build" run: | rm -rf build mkdir build cd build - cmake -DCMAKE_BUILD_TYPE=Debug .. + cmake \ + -DCMAKE_BUILD_TYPE=Debug \ + -DDP_CALLTREE_PROFILING=1 \ + .. make -j3 - name: Python end-to-end-tests diff --git a/CMakeLists.txt b/CMakeLists.txt index ab00d41f1..53fc5a5d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,6 +46,8 @@ For more information, please refer to https://discopop-project.github.io/discopo endif() endif() +find_package(Boost REQUIRED) + message(STATUS "Using LLVM version ${LLVM_PACKAGE_VERSION}") message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") list(APPEND CMAKE_MODULE_PATH ${LLVM_CMAKE_DIR}) @@ -93,6 +95,10 @@ file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build_config.py" "DP_RTLIB_VERBOSE=\"${DP_RTLIB_VERBOSE}\"\n") file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build_config.py" "DP_NUM_WORKERS=\"${DP_NUM_WORKERS}\"\n") file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build_config.py" "DP_INTERNAL_TIMER=\"${DP_INTERNAL_TIMER}\"\n") +file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build_config.py" "DP_CALLTREE_PROFILING=\"${DP_CALLTREE_PROFILING}\"\n") +file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build_config.py" "DP_MEMORY_REGION_DEALIASING=\"${DP_MEMORY_REGION_DEALIASING}\"\n") + + # print DiscoPoP configuration file(READ ${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build_config.py DiscoPoP_CONFIGURATION) diff --git a/discopop_explorer/PEGraphX.py b/discopop_explorer/PEGraphX.py index 3ee63a790..b3fa69a82 100644 --- a/discopop_explorer/PEGraphX.py +++ b/discopop_explorer/PEGraphX.py @@ -142,13 +142,21 @@ class Dependency: sink_line: Optional[LineID] = None intra_iteration: bool = False intra_iteration_level: int = -1 - metadata_intra_iteration_dep: Optional[List[LineID]] = None - metadata_inter_iteration_dep: Optional[List[LineID]] = None - metadata_intra_call_dep: Optional[List[LineID]] = None - metadata_inter_call_dep: Optional[List[LineID]] = None + metadata_intra_iteration_dep: List[LineID] + metadata_inter_iteration_dep: List[LineID] + metadata_intra_call_dep: List[LineID] + metadata_inter_call_dep: List[LineID] + metadata_sink_ancestors: List[LineID] + metadata_source_ancestors: List[LineID] def __init__(self, type: EdgeType): self.etype = type + self.metadata_intra_iteration_dep = [] + self.metadata_inter_iteration_dep = [] + self.metadata_intra_call_dep = [] + self.metadata_inter_call_dep = [] + self.metadata_sink_ancestors = [] + self.metadata_source_ancestors = [] def __str__(self): return self.var_name if self.var_name is not None else str(self.etype) @@ -572,30 +580,27 @@ def parse_dependency(dep: DependenceItem) -> Dependency: d.var_name = dep.var_name d.memory_region = dep.memory_region # parse metadata - if ";" in dep.metadata: - for md in dep.metadata.split(";"): + if len(dep.metadata) > 0: + for md in dep.metadata.split(" "): if len(md) == 0: continue - md_type = md[: md.index(":")] - md_raw_values = md[md.index(":") + 1 :] + # unpack metadata + md_type = md[: md.index("[")] + md_raw_values = md[md.index("[") + 1 : -1] md_values = [tmp for tmp in md_raw_values.split(",") if len(tmp) > 0] - - if md_type == "intra_iteration_dep": - if d.metadata_intra_iteration_dep is None: - d.metadata_intra_iteration_dep = [] + # store metadata + if md_type == "IAI": d.metadata_intra_iteration_dep += md_values - elif md_type == "inter_iteration_dep": - if d.metadata_inter_iteration_dep is None: - d.metadata_inter_iteration_dep = [] + elif md_type == "IEI": d.metadata_inter_iteration_dep += md_values - elif md_type == "intra_call_dep": - if d.metadata_intra_call_dep is None: - d.metadata_intra_call_dep = [] + elif md_type == "IAC": d.metadata_intra_call_dep += md_values - elif md_type == "inter_call_dep": - if d.metadata_inter_call_dep is None: - d.metadata_inter_call_dep = [] + elif md_type == "IEC": d.metadata_inter_call_dep += md_values + elif md_type == "SINK_ANC": + d.metadata_sink_ancestors += md_values + elif md_type == "SOURCE_ANC": + d.metadata_source_ancestors += md_values else: raise ValueError("Unknown metadata type: ", md_type) return d diff --git a/discopop_explorer/parser.py b/discopop_explorer/parser.py index ce895e24a..c950ec9c0 100644 --- a/discopop_explorer/parser.py +++ b/discopop_explorer/parser.py @@ -12,7 +12,7 @@ from collections import defaultdict from dataclasses import dataclass from os.path import abspath, dirname -from typing import Any, List, Tuple +from typing import Any, Dict, List, Tuple from lxml import objectify # type:ignore @@ -113,6 +113,31 @@ def __map_dummy_nodes(cu_dict): def __parse_dep_file(dep_fd, output_path: str) -> Tuple[List[DependenceItem], List[LoopData]]: dependencies_list: List[DependenceItem] = [] loop_data_list: List[LoopData] = [] + + # read dependency metadata + dependency_metadata_lines = [] + if os.path.exists(os.path.join(output_path, "dependency_metadata.txt")): + with open(os.path.join(output_path, "dependency_metadata.txt"), "r") as dep_metadata_fd: + dependency_metadata_lines = dep_metadata_fd.readlines() + dependency_metadata: Dict[Tuple[Any, Any, Any, Any, Any], List[str]] = dict() + for line in dependency_metadata_lines: + line = line.replace("\n", "") + split_line = line.split(" ") + if split_line[0].startswith("#"): + continue + type = split_line[0] + sink = split_line[1] + source = split_line[2] + var = split_line[3] + AAvar = split_line[4] + line_metadata = " ".join( + [split_line[5], split_line[6], split_line[7], split_line[8], split_line[9], split_line[10]] + ) # IAC, IAI, IEC, IEI, SINK_ANC, SOURCE_ANC) + key_tuple = sink, source, type, var, AAvar + if key_tuple not in dependency_metadata: + dependency_metadata[key_tuple] = [] + dependency_metadata[key_tuple].append(line_metadata) + # read static dependencies static_dependency_lines = [] if not os.path.exists(os.path.join(output_path, "static_dependencies.txt")): @@ -155,7 +180,7 @@ def __parse_dep_file(dep_fd, output_path: str) -> Tuple[List[DependenceItem], Li var_str = "" if len(source_fields) == 1 else source_fields[1] var_name = "" aa_var_name = "" - metadata = "" + metadata = [] if len(var_str) > 0: if "(" in var_str: split_var_str = var_str.split("(") @@ -163,13 +188,21 @@ def __parse_dep_file(dep_fd, output_path: str) -> Tuple[List[DependenceItem], Li aa_var_name = split_var_str[1][ : split_var_str[1].index(")") ] # name of the allocated variable which is accessed, i.e. variable name after anti aliasing - metadata_str = split_var_str[1][split_var_str[1].index(")") + 1 :] - if "[" in metadata_str: - metadata = metadata_str[1:-1] else: # compatibility with results created without alias analysis var_name = var_str - dependencies_list.append(DependenceItem(sink, source_fields[0], type, var_name, aa_var_name, metadata)) + # retrieve metadata + key_tuple = sink, source_fields[0], type, var_name, aa_var_name + if key_tuple in dependency_metadata: + metadata = dependency_metadata[key_tuple] + # register dependencies + if len(metadata) == 0: + dependencies_list.append(DependenceItem(sink, source_fields[0], type, var_name, aa_var_name, "")) + else: + for md_set in metadata: + dependencies_list.append( + DependenceItem(sink, source_fields[0], type, var_name, aa_var_name, md_set) + ) return dependencies_list, loop_data_list diff --git a/discopop_explorer/pattern_detectors/do_all_detector.py b/discopop_explorer/pattern_detectors/do_all_detector.py index 96d6f1a24..0b9ea1727 100644 --- a/discopop_explorer/pattern_detectors/do_all_detector.py +++ b/discopop_explorer/pattern_detectors/do_all_detector.py @@ -25,6 +25,7 @@ MemoryRegion, DepType, NodeID, + Dependency, ) from ..utils import classify_loop_variables, filter_for_hotspots from ..variable import Variable @@ -83,6 +84,8 @@ def run_detection(pet: PEGraphX, hotspots, reduction_info: List[ReductionInfo]) result: List[DoAllInfo] = [] nodes = pet.all_nodes(LoopNode) + warnings.warn("DOALL DETECTION CURRENTLY ASSUMES THE EXISTENCE OF DEPENDENCY METADATA!") + # remove reduction loops print("ASDF: ", [r.node_id for r in reduction_info]) print("Nodes: ", [n.start_position() for n in nodes]) @@ -239,10 +242,6 @@ def __check_loop_dependencies( memory_regions_defined_in_loop.update(mem_regs) for source, target, dep in deps: - - if root_loop.start_position() == "1:153": - pass - # todo: move this calculation to the innermost point possible to reduce computation costs # get metadata for dependency dep_source_nesting_level = __calculate_nesting_level(pet, root_loop, source) @@ -264,13 +263,27 @@ def __check_loop_dependencies( if pet.is_loop_index(dep.var_name, loop_start_lines, root_children_cus): continue + # ignore dependencies where either source or sink do not lie within root_loop + if len(dep.metadata_source_ancestors) > 0 and len(dep.metadata_sink_ancestors) > 0: + if not ( + (root_loop.start_position() in dep.metadata_sink_ancestors) + and root_loop.start_position() in dep.metadata_source_ancestors + ): + tmp = root_loop.start_position() + continue + # targeted variable is not read-only if dep.dtype == DepType.INIT: continue elif dep.dtype == DepType.RAW: # check RAW dependencies # RAW problematic, if it is not an intra-iteration RAW - if not dep.intra_iteration: + cond_1 = (len(dep.metadata_intra_iteration_dep) == 0) and parent_function_lineid in ( + dep.metadata_intra_call_dep if dep.metadata_intra_call_dep is not None else [] + ) + cond_2 = len([cf for cf in called_functions_lineids if cf in dep.metadata_inter_call_dep]) > 0 + cond_3 = len([t for t in parent_loops if t in dep.metadata_inter_iteration_dep]) > 0 + if (cond_1) or ((cond_2) and (cond_3)): return True # if it is an intra iteration dependency, it is problematic if it belongs to a parent loop else: @@ -278,20 +291,53 @@ def __check_loop_dependencies( if pet.node_at(source) in root_children_cus and pet.node_at(target) in root_children_cus: pass else: - return True + # check if metadata exists + if dep.metadata_intra_iteration_dep is not None: + for t in dep.metadata_intra_iteration_dep: + if t in parent_loops: + return True + return False + else: + return True elif dep.dtype == DepType.WAR: # check WAR dependencies # WAR problematic, if it is not an intra-iteration WAR and the variable is not private or firstprivate - if not dep.intra_iteration: + if ( + not dep.intra_iteration + and (dep.metadata_intra_iteration_dep is None or len(dep.metadata_intra_iteration_dep) == 0) + and parent_function_lineid + in (dep.metadata_intra_call_dep if dep.metadata_intra_call_dep is not None else []) + ) or ( + ( + False + if dep.metadata_inter_call_dep is None + else (len([cf for cf in called_functions_lineids if cf in dep.metadata_inter_call_dep]) > 0) + ) + and ( + False + if dep.metadata_inter_iteration_dep is None + else (len([t for t in parent_loops if t in dep.metadata_inter_iteration_dep]) > 0) + ) + ): if dep.var_name not in [v.name for v in first_privates + privates + last_privates]: # check if variable is defined inside loop if dep.memory_region not in memory_regions_defined_in_loop: return True + # check if the definitions of the accessed variable originates from a function call + if __check_for_problematic_function_argument_access(pet, source, target, dep): + return True # if it is an intra iteration dependency, it is problematic if it belongs to a parent loop elif dep.intra_iteration_level > root_loop.get_nesting_level(pet): - tmp = root_loop.get_nesting_level(pet) - return True + tmp_nesting_level = root_loop.get_nesting_level(pet) + # check if metadata exists + if len(dep.metadata_intra_iteration_dep) != 0: + for t in dep.metadata_intra_iteration_dep: + if t in parent_loops: + return True + return False + else: + return True elif dep.dtype == DepType.WAW: # check WAW dependencies # handled by variable classification @@ -386,3 +432,35 @@ def __get_called_functions(pet: PEGraphX, root_loop: LoopNode) -> List[LineID]: # convert node ids of called functions to line ids return [pet.node_at(n).start_position() for n in called_functions] + + +def __check_for_problematic_function_argument_access( + pet: PEGraphX, source: NodeID, target: NodeID, dep: Dependency +) -> bool: + """duplicates exists: do_all_detector <-> reduction_detector !""" + # check if the "same" function argument is accessed and it is a pointer type. + # if so, return True. Else. return false + + # find accessed function argument for source + source_pf = pet.get_parent_function(pet.node_at(source)) + source_accessed_pf_args = [a for a in source_pf.args if a.name == dep.var_name] + if len(source_accessed_pf_args) == 0: + return False + + # find accessed function argument for target + target_pf = pet.get_parent_function(pet.node_at(target)) + target_accessed_pf_args = [a for a in target_pf.args if a.name == dep.var_name] + if len(target_accessed_pf_args) == 0: + return False + + # check for overlap in accessed args + + for source_a in source_accessed_pf_args: + for target_a in target_accessed_pf_args: + if source_a == target_a: + # found overlap + # check for pointer type + if "*" in source_a.type: + return True + # not problematic + return False diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index 718302dfc..d51f27a31 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -8,7 +8,8 @@ from multiprocessing import Pool -from typing import List, cast, Set +from typing import List, cast, Set, Tuple +import warnings from alive_progress import alive_bar # type: ignore @@ -23,6 +24,8 @@ DepType, EdgeType, NodeID, + MemoryRegion, + Dependency, ) from ..utils import filter_for_hotspots, is_reduction_var, classify_loop_variables from ..variable import Variable @@ -78,6 +81,8 @@ def run_detection(pet: PEGraphX, hotspots) -> List[ReductionInfo]: nodes = cast(List[LoopNode], filter_for_hotspots(pet, cast(List[Node], nodes), hotspots)) + warnings.warn("REDUCTION DETECTION CURRENTLY ASSUMES THE EXISTENCE OF DEPENDENCY METADATA!") + param_list = [(node) for node in nodes] with Pool(initializer=__initialize_worker, initargs=(pet,)) as pool: tmp_result = list(tqdm.tqdm(pool.imap_unordered(__check_node, param_list), total=len(param_list))) @@ -142,6 +147,17 @@ def __detect_reduction(pet: PEGraphX, root: LoopNode) -> bool: parent_function_lineid = pet.get_parent_function(root).start_position() called_functions_lineids = __get_called_functions(pet, root) + # get variables which are defined inside the loop + defined_inside_loop: List[Tuple[Variable, Set[MemoryRegion]]] = [] + tmp_loop_variables = pet.get_variables(root_children_cus) + for var in tmp_loop_variables: + if ":" in var.defLine: + file_id = int(var.defLine.split(":")[0]) + def_line_num = int(var.defLine.split(":")[1]) + for rc_cu in root_children_cus: + if file_id == rc_cu.file_id and def_line_num >= rc_cu.start_line and def_line_num <= rc_cu.end_line: + defined_inside_loop.append((var, tmp_loop_variables[var])) + if __check_loop_dependencies( pet, root, @@ -152,6 +168,7 @@ def __detect_reduction(pet: PEGraphX, root: LoopNode) -> bool: fp, p, lp, + defined_inside_loop, parent_loops, parent_function_lineid, called_functions_lineids, @@ -176,6 +193,7 @@ def __check_loop_dependencies( first_privates: List[Variable], privates: List[Variable], last_privates: List[Variable], + defined_inside_loop: List[Tuple[Variable, Set[MemoryRegion]]], parent_loops: List[LineID], parent_function_lineid: LineID, called_functions_lineids: List[LineID], @@ -191,6 +209,11 @@ def __check_loop_dependencies( deps.update([(s, t, d) for s, t, d in pet.in_edges(n, EdgeType.DATA) if s in loop_children_ids]) deps.update([(s, t, d) for s, t, d in pet.out_edges(n, EdgeType.DATA) if t in loop_children_ids]) + # get memory regions which are defined inside the loop + memory_regions_defined_in_loop = set() + for var, mem_regs in defined_inside_loop: + memory_regions_defined_in_loop.update(mem_regs) + for source, target, dep in deps: # check if targeted variable is readonly inside loop if pet.is_readonly_inside_loop_body( @@ -207,6 +230,15 @@ def __check_loop_dependencies( if pet.is_loop_index(dep.var_name, loop_start_lines, root_children_cus): continue + # ignore dependencies where either source or sink do not lie within root_loop + if len(dep.metadata_source_ancestors) > 0 and len(dep.metadata_sink_ancestors) > 0: + if not ( + (root_loop.start_position() in dep.metadata_sink_ancestors) + and root_loop.start_position() in dep.metadata_source_ancestors + ): + tmp = root_loop.start_position() + continue + # targeted variable is not read-only if dep.dtype == DepType.INIT: continue @@ -224,14 +256,52 @@ def __check_loop_dependencies( else: # RAW does not target a reduction variable. # RAW problematic, if it is not an intra-iteration RAW. - if not dep.intra_iteration: + if ( + not dep.intra_iteration + and (dep.metadata_intra_iteration_dep is None or len(dep.metadata_intra_iteration_dep) == 0) + and parent_function_lineid + in (dep.metadata_intra_call_dep if dep.metadata_intra_call_dep is not None else []) + ) or ( + ( + False + if dep.metadata_inter_call_dep is None + else (len([cf for cf in called_functions_lineids if cf in dep.metadata_inter_call_dep]) > 0) + ) + and ( + False + if dep.metadata_inter_iteration_dep is None + else (len([t for t in parent_loops if t in dep.metadata_inter_iteration_dep]) > 0) + ) + ): return True elif dep.dtype == DepType.WAR: # check WAR dependencies # WAR problematic, if it is not an intra-iteration WAR and the variable is not private or firstprivate - if not dep.intra_iteration: + if ( + not dep.intra_iteration + and (dep.metadata_intra_iteration_dep is None or len(dep.metadata_intra_iteration_dep) == 0) + and parent_function_lineid + in (dep.metadata_intra_call_dep if dep.metadata_intra_call_dep is not None else []) + ) or ( + ( + False + if dep.metadata_inter_call_dep is None + else (len([cf for cf in called_functions_lineids if cf in dep.metadata_inter_call_dep]) > 0) + ) + and ( + False + if dep.metadata_inter_iteration_dep is None + else (len([t for t in parent_loops if t in dep.metadata_inter_iteration_dep]) > 0) + ) + ): if dep.var_name not in [v.name for v in first_privates + privates + last_privates]: - return True + # check if variable is defined inside loop + if dep.memory_region not in memory_regions_defined_in_loop: + return True + # check if the definitions of the accessed variable originates from a function call + if __check_for_problematic_function_argument_access(pet, source, target, dep): + pass + return True elif dep.dtype == DepType.WAW: # check WAW dependencies # handled by variable classification @@ -286,3 +356,35 @@ def __get_called_functions(pet: PEGraphX, root_loop: LoopNode) -> List[LineID]: # convert node ids of called functions to line ids return [pet.node_at(n).start_position() for n in called_functions] + + +def __check_for_problematic_function_argument_access( + pet: PEGraphX, source: NodeID, target: NodeID, dep: Dependency +) -> bool: + """duplicates exists: do_all_detector <-> reduction_detector !""" + # check if the "same" function argument is accessed and it is a pointer type. + # if so, return True. Else. return false + + # find accessed function argument for source + source_pf = pet.get_parent_function(pet.node_at(source)) + source_accessed_pf_args = [a for a in source_pf.args if a.name == dep.var_name] + if len(source_accessed_pf_args) == 0: + return False + + # find accessed function argument for target + target_pf = pet.get_parent_function(pet.node_at(target)) + target_accessed_pf_args = [a for a in target_pf.args if a.name == dep.var_name] + if len(target_accessed_pf_args) == 0: + return False + + # check for overlap in accessed args + + for source_a in source_accessed_pf_args: + for target_a in target_accessed_pf_args: + if source_a == target_a: + # found overlap + # check for pointer type + if "*" in source_a.type: + return True + # not problematic + return False diff --git a/docs/setup/discopop.md b/docs/setup/discopop.md index d9208a088..c9f93f0af 100644 --- a/docs/setup/discopop.md +++ b/docs/setup/discopop.md @@ -33,6 +33,9 @@ where `` can consist of any combination of the following flags and - `-DDP_PTHREAD_COMPATIBILITY_MODE=[0|1]` – If your application uses PThreads, please specify this flag to serialize the calls to the DiscoPoP runtime functions. Note, however, that this can negatively influence the runtime of the profiling. - `-DDP_NUM_WORKERS=` – Specify the number of worker threads available for the dependency analysis during profiling. Default: `3` worker threads. `0` can be used to disable the creation of additional threads for the analysis. - `-DDP_HYBRID_PROFILING=[0|1]` – Enbale hybrid profiling. Default: `1`. +- `-DDP_CALLTREE_PROFILING=[0|1]` – Enable creation of a call tree during profiling to create extended dependency metadata for improved result quality. Negatively impacts profiling performance. +- `-DDP_MEMORY_REGION_DEALIASING=[0|1]`: Enable or disable the generation of dependency de-aliasing information. Reduces potential false positive parallelization suggestions, but increases the profiling overhead. + #### Development and debugging - `-DDP_RTLIB_VERBOSE=[0|1]` – Enable verbose output during profiling. diff --git a/rtlib/CMakeLists.txt b/rtlib/CMakeLists.txt index 30cca649f..21c26b1a1 100644 --- a/rtlib/CMakeLists.txt +++ b/rtlib/CMakeLists.txt @@ -17,6 +17,13 @@ set(DiscoPoP_SOURCES memory/MemoryManager.cpp memory/Signature.cpp + + calltree/CallTreeNode.cpp + calltree/CallTree.cpp + calltree/CallTreeGlobals.cpp + calltree/DependencyMetadata.cpp + calltree/MetaDataQueueElement.cpp + calltree/utils.cpp injected_functions/dp_add_bb_deps.cpp injected_functions/dp_alloca.cpp @@ -72,6 +79,22 @@ if(DEFINED DP_INTERNAL_TIMER) endif() endif() +if(DEFINED DP_CALLTREE_PROFILING) + if(NOT ${DP_CALLTREE_PROFILING} EQUAL 0) + target_compile_definitions(DiscoPoP_RT PUBLIC DP_CALLTREE_PROFILING=${DP_CALLTREE_PROFILING}) + message(STATUS "WARNING: DiscoPoP configuration: DP_CALLTREE_PROFILING enabled. Reduces profiling speed.") + endif() +endif() + + +if(DEFINED DP_MEMORY_REGION_DEALIASING) + if(NOT ${DP_MEMORY_REGION_DEALIASING} EQUAL 0) + target_compile_definitions(DiscoPoP_RT PUBLIC DP_MEMORY_REGION_DEALIASING=${DP_MEMORY_REGION_DEALIASING}) + message(STATUS "WARNING: DiscoPoP configuration: DP_MEMORY_REGION_DEALIASING enabled. Reduces profiling speed.") + endif() +endif() + + # end of compiler flags install(TARGETS DiscoPoP_RT ARCHIVE DESTINATION lib) diff --git a/rtlib/calltree/CallTree.cpp b/rtlib/calltree/CallTree.cpp new file mode 100644 index 000000000..56ae01849 --- /dev/null +++ b/rtlib/calltree/CallTree.cpp @@ -0,0 +1,94 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +# include "CallTree.hpp" + +namespace __dp +{ + CallTree::CallTree(){ + current = make_shared(); + } + + CallTree::~CallTree(){ + } + + unsigned int CallTree::get_node_count(){ + return call_tree_node_count.load(); + } + + std::shared_ptr CallTree::get_current_node_ptr(){ + return current; + } + + void CallTree::enter_function(unsigned int function_id){ + current = make_shared(current, CallTreeNodeType::Function, function_id, 0); + } + + void CallTree::enter_loop(unsigned int loop_id){ + current = make_shared(current, CallTreeNodeType::Loop, loop_id, 0); + } + + void CallTree::enter_iteration(unsigned int iteration_id){ + // identify loop id of nearest loop + shared_ptr node_ptr = get_current_node_ptr(); + if(! node_ptr){ + return; + } + unsigned int loop_id = 0; + while(node_ptr.get()->get_node_type() != CallTreeNodeType::Root){ + if(node_ptr.get()->get_node_type() == CallTreeNodeType::Loop){ + // found nearest loop node + loop_id = node_ptr.get()->get_loop_or_function_id(); + break; + } + // continue search with parent node + node_ptr = node_ptr.get()->get_parent_ptr(); + } + // create iteration node + current = make_shared(node_ptr, CallTreeNodeType::Iteration, loop_id, iteration_id); + } + + void CallTree::exit_function(){ + // set current to the parent of the closest function + shared_ptr node_ptr = get_current_node_ptr(); + if(! node_ptr){ + return; + } + while(node_ptr->get_node_type() != CallTreeNodeType::Root){ + if(node_ptr->get_node_type() == CallTreeNodeType::Function){ + // found closest function node + break; + } + // continue search with parent + node_ptr = node_ptr->get_parent_ptr(); + } + current = node_ptr->get_parent_ptr(); + } + + void CallTree::exit_loop(){ + // set current to the parent of the closest loop + shared_ptr node_ptr = get_current_node_ptr(); + if(! node_ptr){ + return; + } + while(node_ptr->get_node_type() != CallTreeNodeType::Root){ + if(node_ptr->get_node_type() == CallTreeNodeType::Loop){ + // found closest loop node + break; + } + // continue search with parent + node_ptr = node_ptr->get_parent_ptr(); + } + current = node_ptr->get_parent_ptr(); + } + +} // namespace __dp diff --git a/rtlib/calltree/CallTree.hpp b/rtlib/calltree/CallTree.hpp new file mode 100644 index 000000000..1e9f561a4 --- /dev/null +++ b/rtlib/calltree/CallTree.hpp @@ -0,0 +1,42 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#pragma once + +#include "../DPUtils.hpp" + +#include +#include "CallTreeNode.hpp" +#include "CallTreeGlobals.hpp" +#include + +namespace __dp { + +class CallTree { +public: + CallTree(); + ~CallTree(); + void enter_function(unsigned int function_id); + void exit_function(); + void enter_loop(unsigned int loop_id); + void exit_loop(); + void enter_iteration(unsigned int iteration_id); + // exit_iteration not possible, as determining the iteration end is not trivial + unsigned int get_node_count(); + std::shared_ptr get_current_node_ptr(); + +private: + std::shared_ptr current; + +}; + +} // namespace __dp diff --git a/rtlib/calltree/CallTreeGlobals.cpp b/rtlib/calltree/CallTreeGlobals.cpp new file mode 100644 index 000000000..74abae74a --- /dev/null +++ b/rtlib/calltree/CallTreeGlobals.cpp @@ -0,0 +1,15 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "CallTreeGlobals.hpp" + +std::atomic call_tree_node_count{0}; \ No newline at end of file diff --git a/rtlib/calltree/CallTreeGlobals.hpp b/rtlib/calltree/CallTreeGlobals.hpp new file mode 100644 index 000000000..3e11a3960 --- /dev/null +++ b/rtlib/calltree/CallTreeGlobals.hpp @@ -0,0 +1,17 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#pragma once + +#include + +extern std::atomic call_tree_node_count; \ No newline at end of file diff --git a/rtlib/calltree/CallTreeNode.cpp b/rtlib/calltree/CallTreeNode.cpp new file mode 100644 index 000000000..ac3684073 --- /dev/null +++ b/rtlib/calltree/CallTreeNode.cpp @@ -0,0 +1,74 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "CallTreeNode.hpp" +#include + +namespace __dp { + +CallTreeNode::CallTreeNode(){ + parent_ptr = nullptr; + type = CallTreeNodeType::Root; + loop_or_function_id = 0; + iteration_id = 0; + call_tree_node_count += 1; +} + +CallTreeNode::CallTreeNode(shared_ptr parent_ptr, CallTreeNodeType type, unsigned int loop_or_function_id, unsigned int arg_iteration_id): parent_ptr(parent_ptr), type(type), loop_or_function_id(loop_or_function_id){ + if(type == CallTreeNodeType::Iteration){ + iteration_id = arg_iteration_id; + } + else{ + iteration_id = 0; + } + call_tree_node_count += 1; +} + +CallTreeNode::~CallTreeNode(){ + call_tree_node_count -= 1; +} + +bool CallTreeNode::operator==(const CallTreeNode& other) const{ + // && (iteration_id == other.iteration_id) ignore loop id + if((type == other.type) && (loop_or_function_id == other.loop_or_function_id) ){ + if(parent_ptr && other.parent_ptr){ + if(parent_ptr.get() == other.parent_ptr.get()){ + return true; + } + return false; + } + return false; + } + else{ + return false; + } +} + +shared_ptr CallTreeNode::get_parent_ptr(){ + return parent_ptr; +} + +CallTreeNodeType CallTreeNode::get_node_type(){ + return type; +} + +unsigned int CallTreeNode::get_loop_or_function_id(){ + return loop_or_function_id; +} + +unsigned int CallTreeNode::get_iteration_id(){ + return iteration_id; +} + +} // namespace __dp + + diff --git a/rtlib/calltree/CallTreeNode.hpp b/rtlib/calltree/CallTreeNode.hpp new file mode 100644 index 000000000..4a1f5b214 --- /dev/null +++ b/rtlib/calltree/CallTreeNode.hpp @@ -0,0 +1,41 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#pragma once + +#include "../DPUtils.hpp" +#include "CallTreeNodeType.hpp" +#include "CallTreeGlobals.hpp" + +#include + +namespace __dp { + +class CallTreeNode { +public: + CallTreeNode(); + CallTreeNode(shared_ptr parent_ptr, CallTreeNodeType type, unsigned int loop_or_function_id, unsigned int iteration_id); + ~CallTreeNode(); + bool operator==(const CallTreeNode& other) const; + shared_ptr get_parent_ptr(); + CallTreeNodeType get_node_type(); + unsigned int get_loop_or_function_id(); + unsigned int get_iteration_id(); // only relevant for iteration type nodes, else always 0 +private: + CallTreeNodeType type; + unsigned int loop_or_function_id; // id of the loop or function that is represented by the current node + unsigned int iteration_id; + shared_ptr parent_ptr; + atomic* node_count_ptr; +}; + +} // namespace __dp diff --git a/rtlib/calltree/CallTreeNodeType.hpp b/rtlib/calltree/CallTreeNodeType.hpp new file mode 100644 index 000000000..eeb8d196f --- /dev/null +++ b/rtlib/calltree/CallTreeNodeType.hpp @@ -0,0 +1,24 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#pragma once + +#include "../DPUtils.hpp" + +namespace __dp { + enum class CallTreeNodeType { + Function, + Loop, + Iteration, + Root + }; +} // namespace __dp diff --git a/rtlib/calltree/DependencyMetadata.cpp b/rtlib/calltree/DependencyMetadata.cpp new file mode 100644 index 000000000..433b04578 --- /dev/null +++ b/rtlib/calltree/DependencyMetadata.cpp @@ -0,0 +1,91 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "DependencyMetadata.hpp" + +namespace __dp{ + DependencyMetadata::DependencyMetadata(MetaDataQueueElement mdqe, + std::set arg_intra_call_dependencies, std::set arg_intra_iteration_dependencies, + std::set arg_inter_call_dependencies, std::set arg_inter_iteration_dependencies, + std::set arg_sink_ancestors, std::set arg_source_ancestors): + type(mdqe.type), sink(mdqe.sink), source(mdqe.source), var(mdqe.var), AAvar(mdqe.AAvar), + intra_call_dependencies(arg_intra_call_dependencies), intra_iteration_dependencies(arg_intra_iteration_dependencies), + inter_call_dependencies(arg_inter_call_dependencies), inter_iteration_dependencies(arg_inter_iteration_dependencies), + sink_ancestors(arg_sink_ancestors), source_ancestors(arg_source_ancestors) + { + } + + bool DependencyMetadata::operator==(const DependencyMetadata& other) const{ + return (type == other.type) && (sink == other.sink) && (source == other.source) && (var == other.var) + && (AAvar == other.AAvar) && (intra_call_dependencies == other.intra_call_dependencies) && (intra_iteration_dependencies == other.intra_iteration_dependencies) + && (inter_call_dependencies == other.inter_call_dependencies) && (inter_iteration_dependencies == other.inter_iteration_dependencies) + && (sink_ancestors == other.sink_ancestors) && (source_ancestors == other.source_ancestors); + } + + string DependencyMetadata::toString(){ + string result = ""; + switch (type) + { + case RAW: + result += "RAW "; + break; + case WAR: + result += "WAR "; + break; + case WAW: + result += "WAW "; + break; + case INIT: + result += "INIT "; + break; + default: + break; + } + result += dputil::decodeLID(sink) + " "; + result += dputil::decodeLID(source) + " "; + result += var; + result += " "; + result += AAvar + " "; + result += "IAC["; + for(auto iac : intra_call_dependencies){ + result += dputil::decodeLID(iac) + ","; + } + result += "] "; + result += "IAI["; + for(auto iai : intra_iteration_dependencies){ + result += dputil::decodeLID(iai) + ","; + } + result += "] "; + result += "IEC["; + for(auto iec : inter_call_dependencies){ + result += dputil::decodeLID(iec) + ","; + } + result += "] "; + result += "IEI["; + for(auto iei : inter_iteration_dependencies){ + result += dputil::decodeLID(iei) + ","; + } + result += "] "; + result += "SINK_ANC["; + for(auto sink_anc : sink_ancestors){ + result += dputil::decodeLID(sink_anc) + ","; + } + result += "] "; + result += "SOURCE_ANC["; + for(auto source_anc : source_ancestors){ + result += dputil::decodeLID(source_anc) + ","; + } + result += "] "; + return result; + } + +} // namespace __dp diff --git a/rtlib/calltree/DependencyMetadata.hpp b/rtlib/calltree/DependencyMetadata.hpp new file mode 100644 index 000000000..e00a7be16 --- /dev/null +++ b/rtlib/calltree/DependencyMetadata.hpp @@ -0,0 +1,71 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#pragma once + +#include "../DPUtils.hpp" +#include "../iFunctionsTypes.hpp" +#include "MetaDataQueueElement.hpp" + +namespace __dp +{ + +class DependencyMetadata{ +public: + DependencyMetadata(MetaDataQueueElement mdqe, std::set arg_intra_call_dependencies, std::set arg_intra_iteration_dependencies, std::set arg_inter_call_dependencies, std::set arg_inter_iteration_dependencies, std::set sink_ancestors, std::set arg_source_ancestors); + DependencyMetadata(){} + bool operator==(const DependencyMetadata& other) const; + depType type; + LID sink; + LID source; + const char* var; + string AAvar; + std::set intra_call_dependencies; + std::set intra_iteration_dependencies; + std::set inter_call_dependencies; + std::set inter_iteration_dependencies; + std::set sink_ancestors; + std::set source_ancestors; + string toString(); +}; + +} // namespace __dp + +template <> +struct std::hash<__dp::DependencyMetadata> +{ + std::size_t operator()(const __dp::DependencyMetadata& k) const + { + using boost::hash_value; + using boost::hash_combine; + + // Start with a hash value of 0 . + std::size_t seed = 0; + + // Modify 'seed' by XORing and bit-shifting in + // one member of 'Key' after the other: + hash_combine(seed,hash_value(k.type)); + hash_combine(seed,hash_value(k.sink)); + hash_combine(seed,hash_value(k.source)); + hash_combine(seed,hash_value(k.var)); + hash_combine(seed,hash_value(k.AAvar)); + hash_combine(seed,hash_value(k.intra_call_dependencies)); + hash_combine(seed,hash_value(k.intra_iteration_dependencies)); + hash_combine(seed,hash_value(k.inter_call_dependencies)); + hash_combine(seed,hash_value(k.inter_iteration_dependencies)); + hash_combine(seed,hash_value(k.sink_ancestors)); + hash_combine(seed,hash_value(k.source_ancestors)); + + // Return the result. + return seed; + } +}; \ No newline at end of file diff --git a/rtlib/calltree/MetaDataQueue.cpp b/rtlib/calltree/MetaDataQueue.cpp new file mode 100644 index 000000000..c49dd000b --- /dev/null +++ b/rtlib/calltree/MetaDataQueue.cpp @@ -0,0 +1,139 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "MetaDataQueue.hpp" + +#include "../../share/include/timer.hpp" +#include "../iFunctionsGlobals.hpp" + +namespace __dp +{ + // TODO + MetaDataQueue::MetaDataQueue(int worker_count){ + finalize_queue = false; + + if(worker_count < 1){ + worker_count = 1; + // serial execution + } + for (size_t i = 0; i < worker_count; ++i) + { + // FIX: unnötiges move + threads.emplace_back(std::thread(processQueue, this)); + } + } + + MetaDataQueue::~MetaDataQueue(){ + } + + void MetaDataQueue::insert(MetaDataQueueElement && mdqe){ + const auto calltree_timer = Timer(timers, TimerRegion::ADD_DEP_CALLTREE_REGISTER_METADATAQUEUEELEMENT); + if(finalize_queue){ + return; + } + + // drop the element, if it was already enqueued + bool mdqe_already_enqueued = false; + // check if an equal element was already processed + enqueued_mtx.lock(); + + //mdqe_already_enqueued = enqueued.find(mdqe) != enqueued.end(); + auto contained = enqueued.insert(mdqe); + mdqe_already_enqueued = ! contained.second; + enqueued_mtx.unlock(); + + mdqe_already_enqueued = ! contained.second; + + if(mdqe_already_enqueued){ + // element already inserted to queue before + return; + } + + // insert mdqe to queue + std::lock_guard lock(queue_mtx); + queue.push(std::move(mdqe)); + //cout << "insert: " << mdqe.toString() << "\n"; + } + + int MetaDataQueue::get_size(){ + std::lock_guard lock(queue_mtx); + return queue.size(); + } + + void MetaDataQueue::blocking_finalize_queue(){ + finalize_queue = true; + // join threads + for (auto &t : threads){ + t.join(); + } + + // print results + cout << "RESULTS: \n"; + for(auto dmd: results){ + cout << dmd.toString() << "\n"; + } + + // output to file + std::cout << "Outputting dependency metadata... "; + std::ifstream ifile; + std::string line; + std::ofstream ofile; + std::string tmp(getenv("DOT_DISCOPOP_PROFILER")); + // output information about the loops + tmp += "/dependency_metadata.txt"; + ofile.open(tmp.data()); + ofile << "# IAC : intra-call-dependency \n"; + ofile << "# IAI : intra-iteration-dependency \n"; + ofile << "# IEC : inter-call-dependency \n"; + ofile << "# IEI : inter-iteration-dependency \n"; + ofile << "# SINK_ANC : entered functions and loops for sink location \n"; + ofile << "# SOURCE_ANC : entered functions and loops for source location \n"; + ofile << "# Format: \n"; + for (auto dmd : results) { + ofile << dmd.toString() << "\n"; + } + ofile.close(); + } + + void processQueue(MetaDataQueue* mdq){ + const auto calltree_timer = Timer(timers, TimerRegion::METADATAQUEUE_PROCESSQUEUE); + while(!(mdq->finalize_queue && (mdq->get_size() == 0))){ + mdq->queue_mtx.lock(); + // try fetching an element from the queue + if(mdq->queue.size() != 0){ + const auto calltree_timer = Timer(timers, TimerRegion::METADATAQUEUE_PROCESSQUEUE_FETCH); + + // fetch element from the queue + MetaDataQueueElement mdqe = mdq->queue.front(); + mdq->queue.pop(); + //std::cout << "fetched. Remaining: " << mdq->queue.size() << "\n"; + // release queue lock + mdq->queue_mtx.unlock(); + + // process element + //DependencyMetadata metadata = processQueueElement(mdqe); + + // save metadata to results + mdq->results_mtx.lock(); + mdq->results.push_back(metadata); + mdq->results_mtx.unlock(); + } + else{ + // release lock + mdq->queue_mtx.unlock(); + // sleep 5 milliseconds + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + } + } + } + +} // namespace __dp \ No newline at end of file diff --git a/rtlib/calltree/MetaDataQueue.hpp b/rtlib/calltree/MetaDataQueue.hpp new file mode 100644 index 000000000..fb3ed89ed --- /dev/null +++ b/rtlib/calltree/MetaDataQueue.hpp @@ -0,0 +1,54 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include "MetaDataQueueElement.hpp" +#include "DependencyMetadata.hpp" + + +namespace __dp +{ +class MetaDataQueue{ +public: + MetaDataQueue(int worker_count); // worker_count: minimum 1 + ~MetaDataQueue(); + void insert(MetaDataQueueElement && mdqe); // TODO optimization potential, do not use copies here! + const std::set& get_metadata(); + int get_size(); + void blocking_finalize_queue(); + bool finalize_queue; + std::mutex queue_mtx; + std::queue queue; + std::mutex results_mtx; + std::vector results; + std::mutex enqueued_mtx; + std::unordered_set enqueued; + +private: + std::vector threads; + +}; + +static void processQueue(MetaDataQueue* mdq); +static DependencyMetadata processQueueElement(MetaDataQueueElement mdqe); + + + +} // namespace __dp \ No newline at end of file diff --git a/rtlib/calltree/MetaDataQueueElement.cpp b/rtlib/calltree/MetaDataQueueElement.cpp new file mode 100644 index 000000000..be32447c1 --- /dev/null +++ b/rtlib/calltree/MetaDataQueueElement.cpp @@ -0,0 +1,55 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "MetaDataQueueElement.hpp" + +namespace __dp +{ + MetaDataQueueElement::MetaDataQueueElement(depType arg_type, LID arg_sink, LID arg_source, const char* arg_var, string arg_AAvar, shared_ptr arg_sink_ctn, shared_ptr arg_source_ctn): + type(arg_type), sink(arg_sink), source(arg_source), var(arg_var), AAvar(arg_AAvar), sink_ctn(arg_sink_ctn), source_ctn(arg_source_ctn){ + } + + bool MetaDataQueueElement::operator==(const MetaDataQueueElement& other) const{ + return (type == other.type) && (sink == other.sink) && (source == other.source) && (var == other.var) + && (AAvar == other.AAvar) && (sink_ctn->get_node_type() == other.sink_ctn->get_node_type()) && (sink_ctn->get_loop_or_function_id() == other.sink_ctn->get_loop_or_function_id()) && (sink_ctn->get_iteration_id() == other.sink_ctn->get_iteration_id()) + && (source_ctn->get_node_type() == other.source_ctn->get_node_type()) && (source_ctn->get_loop_or_function_id() == other.source_ctn->get_loop_or_function_id()) && (source_ctn->get_iteration_id() == other.source_ctn->get_iteration_id()); + } + + string MetaDataQueueElement::toString(){ + string result = "MDQE( "; + switch (type) + { + case RAW: + result += "RAW "; + break; + case WAR: + result += "WAR "; + break; + case WAW: + result += "WAW "; + break; + default: + break; + } + result += dputil::decodeLID(sink) + " - " + dputil::decodeLID(source) + " "; + result += var; + result += " "; + result += AAvar + " "; + result += "sink_ctn: " + to_string(sink_ctn->get_loop_or_function_id()) + " "; + result += "it: " + to_string(sink_ctn->get_iteration_id()) + " "; + result += "source_ctn: " + to_string(source_ctn->get_loop_or_function_id()) + " "; + result += "it: " + to_string(source_ctn->get_iteration_id()) + " "; + result += ")"; + return result; + } + +} // namespace __dp \ No newline at end of file diff --git a/rtlib/calltree/MetaDataQueueElement.hpp b/rtlib/calltree/MetaDataQueueElement.hpp new file mode 100644 index 000000000..b77966fe4 --- /dev/null +++ b/rtlib/calltree/MetaDataQueueElement.hpp @@ -0,0 +1,67 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#pragma once + +#include "../DPUtils.hpp" +#include "CallTreeNode.hpp" +#include +#include +#include "../iFunctionsTypes.hpp" + +namespace __dp +{ + +class MetaDataQueueElement{ +public: + MetaDataQueueElement(depType arg_type, LID arg_sink, LID arg_source, const char* arg_var, string arg_AAvar, shared_ptr arg_sink_ctn, shared_ptr arg_source_ctn); + bool operator==(const MetaDataQueueElement& other) const; + string toString(); + depType type; + LID sink; + LID source; + const char* var; + string AAvar; + shared_ptr sink_ctn; + shared_ptr source_ctn; +}; +} + +template <> +struct std::hash<__dp::MetaDataQueueElement> +{ + std::size_t operator()(const __dp::MetaDataQueueElement& k) const + { + using boost::hash_value; + using boost::hash_combine; + + // Start with a hash value of 0 . + std::size_t seed = 0; + + // Modify 'seed' by XORing and bit-shifting in + // one member of 'Key' after the other: + hash_combine(seed,hash_value(k.type)); + hash_combine(seed,hash_value(k.sink)); + hash_combine(seed,hash_value(k.source)); + hash_combine(seed,hash_value(k.var)); + hash_combine(seed,hash_value(k.AAvar)); + hash_combine(seed,hash_value(k.sink_ctn->get_node_type())); + hash_combine(seed,hash_value(k.sink_ctn->get_loop_or_function_id())); + hash_combine(seed,hash_value(k.sink_ctn->get_iteration_id())); + hash_combine(seed,hash_value(k.source_ctn->get_node_type())); + hash_combine(seed,hash_value(k.source_ctn->get_loop_or_function_id())); + hash_combine(seed,hash_value(k.source_ctn->get_iteration_id())); + + // Return the result. + return seed; + } +}; \ No newline at end of file diff --git a/rtlib/calltree/utils.cpp b/rtlib/calltree/utils.cpp new file mode 100644 index 000000000..28d6d1286 --- /dev/null +++ b/rtlib/calltree/utils.cpp @@ -0,0 +1,156 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "utils.hpp" +#include "../../share/include/timer.hpp" +#include "../iFunctionsGlobals.hpp" +#include + +namespace __dp{ + +DependencyMetadata processQueueElement(MetaDataQueueElement mdqe){ + const auto calltree_timer = Timer(timers, TimerRegion::PROCESSQUEUEELEMENT); + + //cout << "processing " << mdqe.toString() << "\n"; + + shared_ptr curr_ctn_node; + // collect ancestors of sink_ctn + curr_ctn_node = mdqe.sink_ctn; + std::set> sink_ctn_ancestors; + std::set sink_ancestor_loops_and_functions; + if(curr_ctn_node){ + while(curr_ctn_node->get_node_type() != CallTreeNodeType::Root){ + if(curr_ctn_node->get_node_type() == CallTreeNodeType::Loop){ + // ignore for metadata calculation, but keep for ancestor reporting + sink_ancestor_loops_and_functions.insert(curr_ctn_node->get_loop_or_function_id()); + } + else{ + sink_ctn_ancestors.insert(curr_ctn_node); + // ancestor reporting + if(curr_ctn_node->get_node_type() == CallTreeNodeType::Function){ + sink_ancestor_loops_and_functions.insert(curr_ctn_node->get_loop_or_function_id()); + } + } + + curr_ctn_node = curr_ctn_node->get_parent_ptr(); + if(!curr_ctn_node){ + break; + } + } + } + + // collect ancestors of source_ctn + curr_ctn_node = mdqe.source_ctn; + std::set> source_ctn_ancestors; + std::set source_ancestor_loops_and_functions; + if(curr_ctn_node){ + while(curr_ctn_node->get_node_type() != CallTreeNodeType::Root){ + if(curr_ctn_node->get_node_type() == CallTreeNodeType::Loop){ + // ignore for metadata calculation, but keep for ancestor reporting + source_ancestor_loops_and_functions.insert(curr_ctn_node->get_loop_or_function_id()); + } + else{ + source_ctn_ancestors.insert(curr_ctn_node); + // ancestor reporting + if(curr_ctn_node->get_node_type() == CallTreeNodeType::Function){ + source_ancestor_loops_and_functions.insert(curr_ctn_node->get_loop_or_function_id()); + } + } + + curr_ctn_node = curr_ctn_node->get_parent_ptr(); + if(!curr_ctn_node){ + break; + } + } + } + + // determine common ancestors + std::set> common_ancestors; + for(auto sink_anc : sink_ctn_ancestors){ + for(auto source_anc : source_ctn_ancestors){ + if(sink_anc == source_anc){ + common_ancestors.insert(sink_anc); + } + } + } + + // determine disjoint ancestors + std::set> disjoint_sink_ancestors; + std::set> disjoint_source_ancestors; + for(auto sink_anc : sink_ctn_ancestors){ + bool contained = false; + for(auto source_anc : source_ctn_ancestors){ + if(sink_anc == source_anc){ + contained = true; + break; + } + } + if(!contained){ + disjoint_sink_ancestors.insert(sink_anc); + } + } + for(auto source_anc : source_ctn_ancestors){ + bool contained = false; + for(auto sink_anc : sink_ctn_ancestors){ + if(source_anc == sink_anc){ + contained = true; + break; + } + } + if(!contained){ + disjoint_source_ancestors.insert(source_anc); + } + } + //cout << "common: " << common_ancestors.size() << " disjoint sink: " << disjoint_sink_ancestors.size() << " source: " << disjoint_source_ancestors.size() << "\n"; + + // identify intra_call and intra_iteration dependencies + std::set intra_call_dependencies; + std::set intra_iteration_dependencies; + for(auto common_anc : common_ancestors){ + if(common_anc->get_node_type() == CallTreeNodeType::Function){ + intra_call_dependencies.insert(common_anc->get_loop_or_function_id()); + } + else if(common_anc->get_node_type() == CallTreeNodeType::Iteration){ + intra_iteration_dependencies.insert(common_anc->get_loop_or_function_id()); + } + } + //cout << "intra_call: " << intra_call_dependencies.size() << " intra_iteration: " << intra_iteration_dependencies.size() << "\n"; + + // identify inter_call and inter_iteration dependencies + std::set inter_call_dependencies; + std::set inter_iteration_dependencies; + for(auto disjoint_sink_anc : disjoint_sink_ancestors){ + for(auto disjoint_source_anc : disjoint_source_ancestors){ + // check for inter call dependencies + if((disjoint_sink_anc->get_node_type() == CallTreeNodeType::Function ) + && (disjoint_source_anc->get_node_type() == CallTreeNodeType::Function) + && (disjoint_sink_anc->get_loop_or_function_id() == disjoint_source_anc->get_loop_or_function_id())){ + inter_call_dependencies.insert(disjoint_sink_anc->get_loop_or_function_id()); + } + // check for inter iteration dependencies + if((disjoint_sink_anc->get_node_type() == CallTreeNodeType::Iteration) + && (disjoint_source_anc->get_node_type() == CallTreeNodeType::Iteration) + && (disjoint_sink_anc->get_parent_ptr() == disjoint_source_anc->get_parent_ptr()) + && (disjoint_sink_anc->get_parent_ptr()->get_node_type() == CallTreeNodeType::Loop) + ){ + inter_iteration_dependencies.insert(disjoint_sink_anc->get_loop_or_function_id()); + } + } + } + //cout << "inter_call: " << inter_call_dependencies.size() << " inter_iteration: " << inter_iteration_dependencies.size() << "\n"; + + return DependencyMetadata(mdqe, intra_call_dependencies, intra_iteration_dependencies, + inter_call_dependencies, inter_iteration_dependencies, + sink_ancestor_loops_and_functions, source_ancestor_loops_and_functions); + } + +} // namespace __dp \ No newline at end of file diff --git a/rtlib/calltree/utils.hpp b/rtlib/calltree/utils.hpp new file mode 100644 index 000000000..c0397ceb0 --- /dev/null +++ b/rtlib/calltree/utils.hpp @@ -0,0 +1,18 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "DependencyMetadata.hpp" +#include "MetaDataQueueElement.hpp" + +namespace __dp{ + DependencyMetadata processQueueElement(MetaDataQueueElement mdqe); +} // namespace __dp diff --git a/rtlib/iFunctions.cpp b/rtlib/iFunctions.cpp index 14dad89ff..5195172bd 100644 --- a/rtlib/iFunctions.cpp +++ b/rtlib/iFunctions.cpp @@ -22,6 +22,7 @@ #include "memory/PerfectShadow.hpp" #include "memory/ShadowMemory.hpp" #include "memory/Signature.hpp" +#include "calltree/utils.hpp" #include #include @@ -55,8 +56,15 @@ namespace __dp { /******* Helper functions *******/ + +#if DP_CALLTREE_PROFILING +void addDep(depType type, LID curr, LID depOn, const char *var, + string AAvar, ADDR addr, std::unordered_map>* thread_private_write_addr_to_call_tree_node_map, std::unordered_map>* thread_private_read_addr_to_call_tree_node_map){ +#else void addDep(depType type, LID curr, LID depOn, const char *var, - string AAvar, ADDR addr) { + string AAvar, ADDR addr){ +#endif + #ifdef DP_INTERNAL_TIMER const auto timer = Timer(timers, TimerRegion::ADD_DEP); #endif @@ -82,6 +90,52 @@ void addDep(depType type, LID curr, LID depOn, const char *var, posInDeps->second->insert(Dep(type, depOn, var, AAvar)); } + +#if DP_CALLTREE_PROFILING + // register dependency for call_tree based metadata calculation + DependencyMetadata dmd; + switch(type){ + case RAW: + // register metadata calculation + //cout << "Register metadata calculation: RAW " << decodeLID(curr) << " " << decodeLID(depOn) << " " << var << " (" << (*thread_private_write_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << (*thread_private_write_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ") " << " (" << (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ")\n"; + + // process directly + dmd = processQueueElement(MetaDataQueueElement(type, curr, depOn, var, AAvar, (*thread_private_read_addr_to_call_tree_node_map)[addr], (*thread_private_write_addr_to_call_tree_node_map)[addr])); + dependency_metadata_results_mtx->lock(); + dependency_metadata_results->insert(dmd); + dependency_metadata_results_mtx->unlock(); + + //metadata_queue->insert(); // optimization potential: do not use copies here! + break; + case WAR: + // update write + // register metadata calculation + //cout << "Register metadata calculation: WAR " << decodeLID(curr) << " " << decodeLID(depOn) << " " << var << " (" << (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ") " << " (" << (*thread_private_write_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << (*thread_private_write_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ")\n"; + + dmd = processQueueElement(MetaDataQueueElement(type, curr, depOn, var, AAvar, (*thread_private_write_addr_to_call_tree_node_map)[addr], (*thread_private_read_addr_to_call_tree_node_map)[addr])); + dependency_metadata_results_mtx->lock(); + dependency_metadata_results->insert(dmd); + dependency_metadata_results_mtx->unlock(); + // metadata_queue->insert(); // optimization potential: do not use copies here! + break; + case WAW: + // register metadata calculation + //cout << "Register metadata calculation: WAW " << decodeLID(curr) << " " << decodeLID(depOn) << " " << var << " (" << (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ") " << " (" << (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ")\n"; + dmd = processQueueElement(MetaDataQueueElement(type, curr, depOn, var, AAvar, (*thread_private_write_addr_to_call_tree_node_map)[addr], (*thread_private_write_addr_to_call_tree_node_map)[addr])); + dependency_metadata_results_mtx->lock(); + dependency_metadata_results->insert(dmd); + dependency_metadata_results_mtx->unlock(); + //metadata_queue->insert(); // optimization potential: do not use copies here! + break; + case INIT: + break; + default: + break; + } + +#endif + + if (DP_DEBUG) { cout << "inserted dep [" << decodeLID(curr) << ", "; switch (type) { @@ -325,7 +379,12 @@ void mergeDeps() { pthread_mutex_unlock(&allDepsLock); } +#if DP_CALLTREE_PROFILING +void analyzeSingleAccess(__dp::AbstractShadow *SMem, __dp::AccessInfo &access, std::unordered_map>* thread_private_write_addr_to_call_tree_node_map, std::unordered_map>* thread_private_read_addr_to_call_tree_node_map) { +#else void analyzeSingleAccess(__dp::AbstractShadow *SMem, __dp::AccessInfo &access) { +#endif + // analyze data dependences #ifdef DP_INTERNAL_TIMER const auto timer = Timer(timers, TimerRegion::ANALYZE_SINGLE_ACCESS); @@ -335,6 +394,11 @@ void analyzeSingleAccess(__dp::AbstractShadow *SMem, __dp::AccessInfo &access) { // hybrid analysis if (access.skip) { SMem->insertToRead(access.addr, access.lid); +#if DP_CALLTREE_PROFILING + //cout << "Acc1 " << access.addr << " " << access.call_tree_node_ptr << "\n"; + (*thread_private_read_addr_to_call_tree_node_map)[access.addr] = access.call_tree_node_ptr; + //cout << "Access read succ\n"; +#endif return; } // End HA @@ -342,28 +406,67 @@ void analyzeSingleAccess(__dp::AbstractShadow *SMem, __dp::AccessInfo &access) { if (lastWrite != 0) { // RAW SMem->insertToRead(access.addr, access.lid); +#if DP_CALLTREE_PROFILING + //cout << "Acc2 " << access.addr << " " << access.call_tree_node_ptr << "\n"; + (*thread_private_read_addr_to_call_tree_node_map)[access.addr] = access.call_tree_node_ptr; + //cout << "Access read succ\n"; +#endif +#if DP_CALLTREE_PROFILING + addDep(RAW, access.lid, lastWrite, access.var, access.AAvar, + access.addr, thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map); +#else addDep(RAW, access.lid, lastWrite, access.var, access.AAvar, access.addr); +#endif } } else { sigElement lastWrite = SMem->insertToWrite(access.addr, access.lid); +#if DP_CALLTREE_PROFILING + //cout << "Acc3 " << access.addr << " " << access.call_tree_node_ptr << "\n"; + //cout << "Acc3-0: " << write_addr_to_call_tree_node_map << "\n"; + + //cout << "Acc3-2 " << write_addr_to_call_tree_node_map << "\n"; + + (*thread_private_write_addr_to_call_tree_node_map)[access.addr] = access.call_tree_node_ptr; + //cout << "Access write succ\n"; +#endif if (lastWrite == 0) { // INIT +#if DP_CALLTREE_PROFILING + addDep(INIT, access.lid, 0, access.var, access.AAvar, + access.addr, thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map); +#else addDep(INIT, access.lid, 0, access.var, access.AAvar, access.addr); +#endif } else { sigElement lastRead = SMem->testInRead(access.addr); if (lastRead != 0) { // WAR +#if DP_CALLTREE_PROFILING + addDep(WAR, access.lid, lastRead, access.var, access.AAvar, + access.addr, thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map); +#else addDep(WAR, access.lid, lastRead, access.var, access.AAvar, access.addr); +#endif // Clear intermediate read ops SMem->insertToRead(access.addr, 0); +#if DP_CALLTREE_PROFILING + //cout << "Acc4 " << access.addr << " " << access.call_tree_node_ptr << "\n"; + (*thread_private_read_addr_to_call_tree_node_map)[access.addr] = access.call_tree_node_ptr; + //cout << "Access read succ\n"; +#endif } else { // WAW +#if DP_CALLTREE_PROFILING + addDep(WAW, access.lid, lastWrite, access.var, access.AAvar, + access.addr, thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map); +#else addDep(WAW, access.lid, lastWrite, access.var, access.AAvar, access.addr); +#endif } } } @@ -382,6 +485,10 @@ void *analyzeDeps(void *arg) { SMem = new ShadowMemory(SIG_ELEM_BIT, SIG_NUM_ELEM, SIG_NUM_HASH); } myMap = new depMap(); +#if DP_CALLTREE_PROFILING + std::unordered_map>* thread_private_write_addr_to_call_tree_node_map = new std::unordered_map>(); + std::unordered_map>* thread_private_read_addr_to_call_tree_node_map = new std::unordered_map>(); +#endif bool isLocked = false; while (true) { if (!isLocked) @@ -406,7 +513,11 @@ void *analyzeDeps(void *arg) { for (unsigned short i = 0; i < CHUNK_SIZE; ++i) { access = accesses[i]; +#if DP_CALLTREE_PROFILING + analyzeSingleAccess(SMem, access, thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map); +#else analyzeSingleAccess(SMem, access); +#endif } // delete the current chunk at the end @@ -432,6 +543,10 @@ void *analyzeDeps(void *arg) { } delete SMem; +#if DP_CALLSTACK_PROFILING + delete thread_private_write_addr_to_call_tree_node_map; + delete thread_private_read_addr_to_call_tree_node_map; +#endif pthread_mutex_unlock(&addrChunkMutexes[id]); mergeDeps(); @@ -478,6 +593,11 @@ void finalizeParallelization() { for (int i = 0; i < NUM_WORKERS; ++i) pthread_join(workers[i], NULL); + +#if DP_CALLTREE_PROFILING + //metadata_queue->blocking_finalize_queue(); +#endif + // destroy mutexes and condition variables for (int i = 0; i < NUM_WORKERS; ++i) { pthread_mutex_destroy(&addrChunkMutexes[i]); diff --git a/rtlib/iFunctionsGlobals.cpp b/rtlib/iFunctionsGlobals.cpp index 1375c6be8..c64a712d5 100644 --- a/rtlib/iFunctionsGlobals.cpp +++ b/rtlib/iFunctionsGlobals.cpp @@ -32,6 +32,10 @@ std::mutex pthread_compatibility_mutex; FunctionManager *function_manager = nullptr; LoopManager *loop_manager = nullptr; MemoryManager *memory_manager = nullptr; +CallTree *call_tree = nullptr; +//MetaDataQueue *metadata_queue = nullptr; +std::mutex* dependency_metadata_results_mtx = nullptr; +std::unordered_set* dependency_metadata_results = nullptr; // hybrid analysis ReportedBBSet *bbList = nullptr; diff --git a/rtlib/iFunctionsGlobals.hpp b/rtlib/iFunctionsGlobals.hpp index 4f4e3a7e9..60b4121b5 100644 --- a/rtlib/iFunctionsGlobals.hpp +++ b/rtlib/iFunctionsGlobals.hpp @@ -15,6 +15,8 @@ #include "../share/include/timer.hpp" #include "iFunctionsTypes.hpp" #include "memory/AbstractShadow.hpp" +#include "calltree/CallTree.hpp" +#include "calltree/DependencyMetadata.hpp" #include @@ -49,6 +51,10 @@ extern std::mutex pthread_compatibility_mutex; extern FunctionManager *function_manager; extern LoopManager *loop_manager; extern MemoryManager *memory_manager; +extern CallTree *call_tree; +//extern MetaDataQueue * metadata_queue; +extern std::mutex* dependency_metadata_results_mtx; +extern std::unordered_set* dependency_metadata_results; // hybrid analysis extern ReportedBBSet *bbList; diff --git a/rtlib/iFunctionsTypes.hpp b/rtlib/iFunctionsTypes.hpp index 34234310e..f0e0b0511 100644 --- a/rtlib/iFunctionsTypes.hpp +++ b/rtlib/iFunctionsTypes.hpp @@ -18,6 +18,10 @@ #include "loop/LoopManager.hpp" #include "memory/MemoryManager.hpp" +#if DP_CALLTREE_PROFILING +#include "calltree/CallTreeNode.hpp" +#endif + #include #include #include @@ -54,9 +58,17 @@ typedef enum { struct AccessInfo { AccessInfo(bool isRead, LID lid, char *var, std::string AAvar, ADDR addr, bool skip = false) - : isRead(isRead), lid(lid), var(var), AAvar(AAvar), addr(addr), skip(skip) {} - - AccessInfo() : isRead(false), lid(0), var(""), AAvar(""), addr(0), skip(false) {} + : isRead(isRead), lid(lid), var(var), AAvar(AAvar), addr(addr), skip(skip) { +#if DP_CALLTREE_PROFILING + call_tree_node_ptr = nullptr; +#endif + } + + AccessInfo() : isRead(false), lid(0), var(""), AAvar(""), addr(0), skip(false) { +#if DP_CALLTREE_PROFILING + call_tree_node_ptr = nullptr; +#endif + } bool isRead; // hybrid analysis @@ -66,6 +78,9 @@ struct AccessInfo { const char *var; std::string AAvar; // name of allocated variable -> "Anti Aliased Variable" ADDR addr; +#if DP_CALLTREE_PROFILING + shared_ptr call_tree_node_ptr; +#endif }; // For runtime dependency merging diff --git a/rtlib/injected_functions/dp_alloca.cpp b/rtlib/injected_functions/dp_alloca.cpp index 8aca0f553..cc2d278da 100644 --- a/rtlib/injected_functions/dp_alloca.cpp +++ b/rtlib/injected_functions/dp_alloca.cpp @@ -47,8 +47,12 @@ void __dp_alloca(LID lid, char *var, ADDR startAddr, ADDR endAddr, int64_t numBy #endif #if DP_MEMORY_REGION_DEALIASING +#if DP_STACK_ACCESS_DETECTION // create entry to list of allocatedMemoryRegions const std::string allocId = memory_manager->allocate_stack_memory(lid, startAddr, endAddr, numBytes, numElements); +#else + const std::string allocId = memory_manager->allocate_memory(lid, startAddr, endAddr, numBytes, numElements); +#endif // std::cout << "alloca: " << var << " (" << allocId << ") @ " << // dputil::decodeLID(lid) << " : " << std::hex << startAddr << " - " << // std::hex << endAddr << " -> #allocations: " << diff --git a/rtlib/injected_functions/dp_finalize.cpp b/rtlib/injected_functions/dp_finalize.cpp index 1e16f8111..7a68038c1 100644 --- a/rtlib/injected_functions/dp_finalize.cpp +++ b/rtlib/injected_functions/dp_finalize.cpp @@ -156,6 +156,35 @@ void __dp_finalize(LID lid) { delete function_manager; delete loop_manager; + +#ifdef DP_CALLTREE_PROFILING + delete call_tree; + //delete metadata_queue; + // output metadata to file + std::cout << "Outputting dependency metadata... "; + std::ifstream ifile; + std::string line; + std::ofstream ofile; + std::string tmp(getenv("DOT_DISCOPOP_PROFILER")); + // output information about the loops + tmp += "/dependency_metadata.txt"; + ofile.open(tmp.data()); + ofile << "# IAC : intra-call-dependency \n"; + ofile << "# IAI : intra-iteration-dependency \n"; + ofile << "# IEC : inter-call-dependency \n"; + ofile << "# IEI : inter-iteration-dependency \n"; + ofile << "# SINK_ANC : entered functions and loops for sink location \n"; + ofile << "# SOURCE_ANC : entered functions and loops for source location \n"; + ofile << "# Format: \n"; + for (auto dmd : *dependency_metadata_results) { + ofile << dmd.toString() << "\n"; + } + ofile.close(); + delete dependency_metadata_results_mtx; + delete dependency_metadata_results; +#endif + + *out << dputil::decodeLID(lid) << " END program" << endl; out->flush(); out->close(); diff --git a/rtlib/injected_functions/dp_func_entry.cpp b/rtlib/injected_functions/dp_func_entry.cpp index 7ccd3b006..a9ada7ba4 100644 --- a/rtlib/injected_functions/dp_func_entry.cpp +++ b/rtlib/injected_functions/dp_func_entry.cpp @@ -58,6 +58,12 @@ void __dp_func_entry(LID lid, int32_t isStart) { function_manager = new FunctionManager(); loop_manager = new LoopManager(); memory_manager = new MemoryManager(); +#if DP_CALLTREE_PROFILING + call_tree = new CallTree(); + //metadata_queue = new MetaDataQueue(6); // TODO: add Worker argument + dependency_metadata_results_mtx = new std::mutex(); + dependency_metadata_results = new std::unordered_set(); +#endif out = new ofstream(); @@ -126,6 +132,11 @@ void __dp_func_entry(LID lid, int32_t isStart) { memory_manager->enterScope("function", lid); #endif +#ifdef DP_CALLTREE_PROFILING + call_tree->enter_function(lid); +#endif + + if (isStart) *out << "START " << dputil::decodeLID(lid) << endl; diff --git a/rtlib/injected_functions/dp_func_exit.cpp b/rtlib/injected_functions/dp_func_exit.cpp index b177a5c5a..fad56ca48 100644 --- a/rtlib/injected_functions/dp_func_exit.cpp +++ b/rtlib/injected_functions/dp_func_exit.cpp @@ -78,6 +78,10 @@ void __dp_func_exit(LID lid, int32_t isExit) { #if DP_STACK_ACCESS_DETECTION memory_manager->leaveScope("function", lid); #endif + +#ifdef DP_CALLTREE_PROFILING + call_tree->exit_function(); +#endif // !TEST if (isExit == 0) { diff --git a/rtlib/injected_functions/dp_loop_entry.cpp b/rtlib/injected_functions/dp_loop_entry.cpp index e38cb3032..ad72c3d37 100644 --- a/rtlib/injected_functions/dp_loop_entry.cpp +++ b/rtlib/injected_functions/dp_loop_entry.cpp @@ -64,6 +64,11 @@ void __dp_loop_entry(LID lid, int32_t loopID) { memory_manager->enterScope("loop", lid); #endif +#ifdef DP_CALLTREE_PROFILING + call_tree->enter_loop(lid); + call_tree->enter_iteration(0); +#endif + } else { // The same loop iterates again loop_manager->iterate_loop(function_stack_level); @@ -86,6 +91,10 @@ void __dp_loop_entry(LID lid, int32_t loopID) { memory_manager->leaveScope("loop_iteration", lid); memory_manager->enterScope("loop_iteration", lid); #endif + +#ifdef DP_CALLTREE_PROFILING + call_tree->enter_iteration(0); +#endif } } } diff --git a/rtlib/injected_functions/dp_loop_exit.cpp b/rtlib/injected_functions/dp_loop_exit.cpp index 8dd7f0199..e427902f8 100644 --- a/rtlib/injected_functions/dp_loop_exit.cpp +++ b/rtlib/injected_functions/dp_loop_exit.cpp @@ -72,6 +72,10 @@ void __dp_loop_exit(LID lid, int32_t loopID) { #if DP_STACK_ACCESS_DETECTION memory_manager->leaveScope("loop", lid); #endif + +#ifdef DP_CALLTREE_PROFILING + call_tree->exit_loop(); +#endif } } diff --git a/rtlib/injected_functions/dp_read.cpp b/rtlib/injected_functions/dp_read.cpp index 2bc02b643..e3b18b5ca 100644 --- a/rtlib/injected_functions/dp_read.cpp +++ b/rtlib/injected_functions/dp_read.cpp @@ -90,6 +90,9 @@ void __dp_read(LID lid, ADDR addr, const char *var) { current.var = var; current.AAvar = getMemoryRegionIdFromAddr(var, addr); current.addr = addr; +#if DP_CALLTREE_PROFILING + current.call_tree_node_ptr = call_tree->get_current_node_ptr(); +#endif #if defined DP_NUM_WORKERS && DP_NUM_WORKERS == 0 analyzeSingleAccess(singleThreadedExecutionSMem, current); diff --git a/rtlib/injected_functions/dp_write.cpp b/rtlib/injected_functions/dp_write.cpp index bb9298670..42d48b4d8 100644 --- a/rtlib/injected_functions/dp_write.cpp +++ b/rtlib/injected_functions/dp_write.cpp @@ -93,6 +93,10 @@ void __dp_write(LID lid, ADDR addr, const char *var) { current.AAvar = getMemoryRegionIdFromAddr(var, addr); current.addr = addr; +#if DP_CALLTREE_PROFILING + current.call_tree_node_ptr = call_tree->get_current_node_ptr(); +#endif + #if defined DP_NUM_WORKERS && DP_NUM_WORKERS == 0 analyzeSingleAccess(singleThreadedExecutionSMem, current); #else diff --git a/share/include/timer.hpp b/share/include/timer.hpp index 2a06e2115..416aa1331 100644 --- a/share/include/timer.hpp +++ b/share/include/timer.hpp @@ -66,6 +66,13 @@ enum class TimerRegion : unsigned int { STACK_CHECK_ADDR_IS_OWNED_BY_SCOPE, STACK_CHECK_ADDR_IS_OWNED_BY_SCOPE_TRUE, + // Statistics regarding calltree profiling + ADD_DEP_CALLTREE_REGISTER_METADATAQUEUEELEMENT, + METADATAQUEUE_PROCESSQUEUE, + METADATAQUEUE_PROCESSQUEUEELEMENT, + METADATAQUEUE_PROCESSQUEUE_FETCH, + PROCESSQUEUEELEMENT, + SIZE_DONT_USE, }; @@ -183,11 +190,11 @@ class Timers { print(stream, " Finalizing the parallelization : ", TimerRegion::FINALIZE_PARALLELIZATION); stream << '\n'; print(stream, " Generate the dependency map : ", TimerRegion::GENERATE_STRING_DEP_MAP); - print(stream, " Add a dependency : ", TimerRegion::ADD_DEP); + print(stream, " Analyze singe accesses : ", TimerRegion::ANALYZE_SINGLE_ACCESS); + print(stream, " |- Add a dependency : ", TimerRegion::ADD_DEP); print(stream, " Merge dendencies : ", TimerRegion::MERGE_DEPS); print(stream, " Analyze the dependencies (incorrect!) : ", TimerRegion::ANALYZE_DEPS); // Incorrect due to multithreading - print(stream, " Analyze singe accesses : ", TimerRegion::ANALYZE_SINGLE_ACCESS); stream << '\n'; print(stream, " Output the dependencies : ", TimerRegion::OUTPUT_DEPS); print(stream, " Output the loops : ", TimerRegion::OUTPUT_LOOPS); @@ -210,6 +217,20 @@ class Timers { " Check for addr is owned by scope : ", TimerRegion::STACK_CHECK_ADDR_IS_OWNED_BY_SCOPE); print(stream, " Found addr is owned by scope : ", TimerRegion::STACK_CHECK_ADDR_IS_OWNED_BY_SCOPE_TRUE); + stream << "\n"; + +#if DP_CALLTREE_PROFILING + stream << "\n========== DiscoPoP TIMERS: calltree profiling ======\n"; + print(stream, " Context: Analyze singe accesses : ", TimerRegion::ANALYZE_SINGLE_ACCESS); + print(stream, " |- Context: Add a dependency : ", TimerRegion::ADD_DEP); + print(stream, " |- Register MetaDataQueueElements : ", TimerRegion::ADD_DEP_CALLTREE_REGISTER_METADATAQUEUEELEMENT); + print(stream, " MetaDataQueue: processQueue : ", TimerRegion::METADATAQUEUE_PROCESSQUEUE); + print(stream, " |- Fetch MetaDataQueueElement : ", TimerRegion::METADATAQUEUE_PROCESSQUEUE_FETCH); + print(stream, " |- processQueueElement : ", TimerRegion::METADATAQUEUE_PROCESSQUEUEELEMENT); + print(stream, " Stand-alone processQueueElement : ", TimerRegion::PROCESSQUEUEELEMENT); + stream << "\n"; +#endif + } /** diff --git a/test/end_to_end/do_all/calls/complex/src/code.cpp b/test/end_to_end/do_all/calls/complex/src/code.cpp index c9b270554..8572d56c4 100644 --- a/test/end_to_end/do_all/calls/complex/src/code.cpp +++ b/test/end_to_end/do_all/calls/complex/src/code.cpp @@ -10,7 +10,7 @@ void doall_possible(double* base, int index){ } void doall_not_possible(double* base, int index, int n){ - perform_calculation(base, index, (index + 1 % n)); + perform_calculation(base, index, (index + 422 % n)); } int main(int argc, const char* argv[]) { diff --git a/test/end_to_end/do_all/calls/complex_no_varname_duplicates/__init__.py b/test/end_to_end/do_all/calls/complex_no_varname_duplicates/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/end_to_end/do_all/calls/complex_no_varname_duplicates/src/Makefile b/test/end_to_end/do_all/calls/complex_no_varname_duplicates/src/Makefile new file mode 100644 index 000000000..a64882be3 --- /dev/null +++ b/test/end_to_end/do_all/calls/complex_no_varname_duplicates/src/Makefile @@ -0,0 +1,17 @@ +all: clean prog + +prog: code.o + $(CXX) -o prog code.o $(CXXFLAGS) + +code.o: + $(CXX) -c -S -emit-llvm -o code.ll code.cpp $(CXXFLAGS) + rm -rf .discopop + $(CXX) -c -o code.o code.cpp $(CXXFLAGS) + +clean: + rm -rf .discopop + rm -rf src/.discopop + find . -not -name code.cpp -not -name Makefile -not -path **/FileMapping.txt -delete + +veryclean: clean + rm -f FileMapping.txt diff --git a/test/end_to_end/do_all/calls/complex_no_varname_duplicates/src/code.cpp b/test/end_to_end/do_all/calls/complex_no_varname_duplicates/src/code.cpp new file mode 100644 index 000000000..299195a8f --- /dev/null +++ b/test/end_to_end/do_all/calls/complex_no_varname_duplicates/src/code.cpp @@ -0,0 +1,40 @@ +#include +#include + +void perform_calculation(double* base_1, int offset_1, int offset_2){ + base_1[offset_1] = 42 + base_1[offset_2]; +} + +void doall_possible(double* base_2, int index_2){ + perform_calculation(base_2, index_2, index_2); +} + +void doall_not_possible(double* base_3, int index_3, int n_3){ + perform_calculation(base_3, index_3, (index_3 + 422 % n_3)); +} + +int main(int argc, const char* argv[]) { + static int n = 5000; static double a = 2.0; //n = 100000000; + double *x = (double *) malloc(n * sizeof(double)); + // Initialize x + + // DOALL + for(int i = 0; i < n; ++i){ + x[i] = 1.0; + } + + // DOALL + for(int i = 0; i < n; i++){ + doall_possible(x, i); + } + + // NOT DOALL + for(int i = 0; i < n; i++){ + doall_not_possible(x, i, n); + } + + + free(x);; +return 0; +} + diff --git a/test/end_to_end/do_all/calls/complex_no_varname_duplicates/test.py b/test/end_to_end/do_all/calls/complex_no_varname_duplicates/test.py new file mode 100644 index 000000000..bc7d22eb0 --- /dev/null +++ b/test/end_to_end/do_all/calls/complex_no_varname_duplicates/test.py @@ -0,0 +1,74 @@ +import os +import pathlib +import subprocess +import unittest + +import jsonpickle + +from discopop_library.result_classes.DetectionResult import DetectionResult +from test.utils.subprocess_wrapper.command_execution_wrapper import run_cmd +from test.utils.validator_classes.DoAllInfoForValidation import DoAllInfoForValidation +from subprocess import DEVNULL +from discopop_library.ConfigProvider.config_provider import run as run_config_provider +from discopop_library.ConfigProvider.ConfigProviderArguments import ConfigProviderArguments + + +class TestMethods(unittest.TestCase): + def test(self): + current_dir = pathlib.Path(__file__).parent.resolve() + dp_build_dir = run_config_provider( + ConfigProviderArguments( + return_dp_build_dir=True, + return_dp_source_dir=False, + return_llvm_bin_dir=False, + return_full_config=False, + return_version_string=False, + ) + ) + + env_vars = dict(os.environ) + + src_dir = os.path.join(current_dir, "src") + # create FileMapping + cmd = os.path.join(dp_build_dir, "scripts", "dp-fmap") + run_cmd(cmd, src_dir, env_vars) + + # build + env_vars["CC"] = os.path.join(dp_build_dir, "scripts", "CC_wrapper.sh") + env_vars["CXX"] = os.path.join(dp_build_dir, "scripts", "CXX_wrapper.sh") + cmd = "make" + run_cmd(cmd, src_dir, env_vars) + + # execute instrumented program + run_cmd("./prog", src_dir, env_vars) + + # execute DiscoPoP analysis + cmd = "discopop_explorer --enable-patterns doall,reduction" + run_cmd(cmd, os.path.join(src_dir, ".discopop"), env_vars) + # validate results + try: + self.validate_results(current_dir, src_dir) + # clean environment + run_cmd("make veryclean", src_dir, env_vars) + except Exception as ex: + # clean environment + run_cmd("make veryclean", src_dir, env_vars) + raise ex + + def validate_results(self, test_dir, src_dir): + """Check that exactly one do-all is suggested""" + test_output_file = os.path.join(src_dir, ".discopop", "explorer", "detection_result_dump.json") + # load detection results + with open(test_output_file, "r") as f: + tmp_str = f.read() + test_output: DetectionResult = jsonpickle.decode(tmp_str) + + for pattern_type in test_output.patterns.__dict__: + amount_of_identified_patterns = len(test_output.patterns.__dict__[pattern_type]) + if pattern_type == "do_all": + expected = ["1:22", "1:27"] + for pattern in test_output.patterns.__dict__[pattern_type]: + self.assertTrue(pattern.start_line in expected, "False positive: Pattern at " + pattern.start_line + " not in expected result: " + str(expected)) + self.assertTrue(len(test_output.patterns.__dict__[pattern_type]) == 2, "False negative: Missed pattern. \nFound: " + " ".join([p.start_line for p in test_output.patterns.__dict__[pattern_type]])+"\nExpected: " + " ".join(expected)) + else: + self.assertEqual(amount_of_identified_patterns, 0) \ No newline at end of file diff --git a/test/unit_tests/CMakeLists.txt b/test/unit_tests/CMakeLists.txt index e76c48326..af3be329c 100644 --- a/test/unit_tests/CMakeLists.txt +++ b/test/unit_tests/CMakeLists.txt @@ -38,7 +38,10 @@ target_sources( memory/memory_region_tree/test_memory_region_tree.cpp memory/mrtnode/test_mrtnode.cpp memory/perfect_shadow/test_perfect_shadow.cpp - memory/scope/test_scope.cpp) + memory/scope/test_scope.cpp + calltree/call_tree/test_call_tree.cpp + calltree/call_tree_node/test_call_tree_node.cpp + calltree/metadata_queue/test_metadata_queue.cpp) target_include_directories(DiscoPoP_UT PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(DiscoPoP_UT PRIVATE DiscoPoP_RT) diff --git a/test/unit_tests/calltree/call_tree/test_call_tree.cpp b/test/unit_tests/calltree/call_tree/test_call_tree.cpp new file mode 100644 index 000000000..f53102162 --- /dev/null +++ b/test/unit_tests/calltree/call_tree/test_call_tree.cpp @@ -0,0 +1,162 @@ +#include + +#include "../../../../rtlib/calltree/CallTree.hpp" + +#include +#include + +// Tests for old version (i.e., capturing functionality) + +class CallTreeTest : public ::testing::Test {}; + +TEST_F(CallTreeTest, testConstructor) { + auto ct = __dp::CallTree(); + + ASSERT_EQ(call_tree_node_count.load(), 1); + ASSERT_EQ(ct.get_current_node_ptr()->get_node_type(), __dp::CallTreeNodeType::Root); +} + +TEST_F(CallTreeTest, testIncreasingNodeCount) { + auto ct = __dp::CallTree(); + + ASSERT_EQ(ct.get_node_count(), 1); + ct.enter_function(42); + ASSERT_EQ(ct.get_node_count(), 2); + ct.enter_function(43); + ASSERT_EQ(ct.get_node_count(), 3); +} + +TEST_F(CallTreeTest, testDecreasingNodeCount) { + auto ct = __dp::CallTree(); + + ASSERT_EQ(ct.get_node_count(), 1); + ct.enter_function(42); + ASSERT_EQ(ct.get_node_count(), 2); + ct.enter_function(43); + ASSERT_EQ(ct.get_node_count(), 3); + ct.exit_function(); + ASSERT_EQ(ct.get_node_count(), 2); + ct.exit_function(); + ASSERT_EQ(ct.get_node_count(), 1); +} + +TEST_F(CallTreeTest, testEnterLoop) { + auto ct = __dp::CallTree(); + ct.enter_loop(42); + + ASSERT_EQ(ct.get_node_count(), 2); + ASSERT_EQ(ct.get_current_node_ptr()->get_node_type(), __dp::CallTreeNodeType::Loop); + ASSERT_EQ(ct.get_current_node_ptr()->get_loop_or_function_id(), 42); +} + +TEST_F(CallTreeTest, testExitLoop){ + auto ct = __dp::CallTree(); + ct.enter_function(42); + ct.enter_loop(43); + ct.enter_iteration(1); + ct.enter_iteration(2); + ct.exit_loop(); + + ASSERT_EQ(ct.get_current_node_ptr()->get_node_type(), __dp::CallTreeNodeType::Function); + ASSERT_EQ(ct.get_current_node_ptr()->get_loop_or_function_id(), 42) ; + ASSERT_EQ(ct.get_node_count(), 2); +} + +TEST_F(CallTreeTest, testEnterFunction) { + auto ct = __dp::CallTree(); + ct.enter_function(42); + + ASSERT_EQ(ct.get_node_count(), 2); + ASSERT_EQ(ct.get_current_node_ptr()->get_node_type(), __dp::CallTreeNodeType::Function); + ASSERT_EQ(ct.get_current_node_ptr()->get_loop_or_function_id(), 42); +} + +TEST_F(CallTreeTest, testExitFunctionSimple){ + auto ct = __dp::CallTree(); + ct.enter_function(42); + ct.enter_loop(43); + ct.enter_iteration(1); + ct.enter_iteration(2); + ct.exit_function(); + + ASSERT_EQ(ct.get_current_node_ptr()->get_node_type(), __dp::CallTreeNodeType::Root); + ASSERT_EQ(ct.get_node_count(), 1); +} + +TEST_F(CallTreeTest, testExitFunction){ + auto ct = __dp::CallTree(); + ct.enter_function(42); + ct.enter_loop(43); + ct.enter_iteration(1); + ct.enter_iteration(2); + ct.exit_loop(); + ct.enter_loop(44); + ct.enter_iteration(1); + // ct.exit_loop(); missing on purpose + ct.exit_function(); + + ASSERT_EQ(ct.get_current_node_ptr()->get_node_type(), __dp::CallTreeNodeType::Root); + ASSERT_EQ(ct.get_node_count(), 1); +} + + +TEST_F(CallTreeTest, testEnterIterations) { + auto ct = __dp::CallTree(); + ct.enter_loop(42); + + ASSERT_EQ(ct.get_node_count(), 2); + ASSERT_EQ(ct.get_current_node_ptr()->get_node_type(), __dp::CallTreeNodeType::Loop); + ASSERT_EQ(ct.get_current_node_ptr()->get_loop_or_function_id(), 42); + + ct.enter_iteration(1); + ASSERT_EQ(ct.get_node_count(), 3); + ASSERT_EQ(ct.get_current_node_ptr()->get_node_type(), __dp::CallTreeNodeType::Iteration); + ASSERT_EQ(ct.get_current_node_ptr()->get_loop_or_function_id(), 42); + ASSERT_EQ(ct.get_current_node_ptr()->get_iteration_id(), 1); + + ct.enter_iteration(2); + // node of iteration 1 will be deleted, as ct.current pointer is redirected + ASSERT_EQ(ct.get_node_count(), 3); + ASSERT_EQ(ct.get_current_node_ptr()->get_node_type(), __dp::CallTreeNodeType::Iteration); + ASSERT_EQ(ct.get_current_node_ptr()->get_loop_or_function_id(), 42); + ASSERT_EQ(ct.get_current_node_ptr()->get_iteration_id(), 2); +} + +TEST_F(CallTreeTest, testAutomaticCleanup){ + auto ct = __dp::CallTree(); + ct.enter_function(42); + ct.enter_loop(43); + ct.enter_iteration(1); + ASSERT_EQ(ct.get_node_count(), 4); + + ct.enter_iteration(2); + // iteration node 1 shall be deleted, since it is not referenced anymore + ASSERT_EQ(ct.get_node_count(), 4); +} + +TEST_F(CallTreeTest, testPreventAutomaticCleanup){ + auto ct = __dp::CallTree(); + ct.enter_function(42); + ct.enter_loop(43); + ct.enter_iteration(1); + ASSERT_EQ(ct.get_node_count(), 4); + + { + // save ptr to iteration 1 to prevent cleanup + std::shared_ptr<__dp::CallTreeNode> dummy_ptr = ct.get_current_node_ptr(); + + ct.enter_iteration(2); + // iteration node 1 shall NOT be deleted, since a referenced still exists + ASSERT_EQ(ct.get_node_count(), 5); + } + + // dummy_ptr shall now be deleted. Check for automatic cleanup of iteration node 1 + ASSERT_EQ(ct.get_node_count(), 4); +} + +TEST_F(CallTreeTest, testImmediateFuncExit){ + auto ct = __dp::CallTree(); + ct.exit_function(); + // check for segfaults + ASSERT_TRUE(true); +} diff --git a/test/unit_tests/calltree/call_tree_node/test_call_tree_node.cpp b/test/unit_tests/calltree/call_tree_node/test_call_tree_node.cpp new file mode 100644 index 000000000..aa118eb88 --- /dev/null +++ b/test/unit_tests/calltree/call_tree_node/test_call_tree_node.cpp @@ -0,0 +1,74 @@ +#include + +#include "../../../../rtlib/calltree/CallTreeNode.hpp" +#include "../../../../rtlib/calltree/CallTreeNodeType.hpp" + +class CallTreeNodeTest : public ::testing::Test {}; + +TEST_F(CallTreeNodeTest, testConstructor) { + auto ctn = __dp::CallTreeNode( nullptr, __dp::CallTreeNodeType::Function, 1, 0); + + ASSERT_EQ(ctn.get_loop_or_function_id(), 1); + ASSERT_EQ(ctn.get_node_type(), __dp::CallTreeNodeType::Function); +} + +TEST_F(CallTreeNodeTest, testDefaultConstructor) { + auto ctn = __dp::CallTreeNode(); + + ASSERT_EQ(ctn.get_loop_or_function_id(), 0); + ASSERT_EQ(ctn.get_node_type(), __dp::CallTreeNodeType::Root); + ASSERT_EQ(ctn.get_iteration_id(), 0); + ASSERT_EQ(ctn.get_parent_ptr(), nullptr); +} + +TEST_F(CallTreeNodeTest, testGetIterationId) { + auto ctn = __dp::CallTreeNode( nullptr, __dp::CallTreeNodeType::Root, 0, 0); + ASSERT_EQ(ctn.get_loop_or_function_id(), 0); + ASSERT_EQ(ctn.get_node_type(), __dp::CallTreeNodeType::Root); + ASSERT_EQ(ctn.get_iteration_id(), 0); + + ctn = __dp::CallTreeNode( nullptr, __dp::CallTreeNodeType::Root, 0, 1); + ASSERT_EQ(ctn.get_loop_or_function_id(), 0); + ASSERT_EQ(ctn.get_node_type(), __dp::CallTreeNodeType::Root); + ASSERT_EQ(ctn.get_iteration_id(), 0); + + ctn = __dp::CallTreeNode( nullptr, __dp::CallTreeNodeType::Function, 1, 0); + ASSERT_EQ(ctn.get_loop_or_function_id(), 1); + ASSERT_EQ(ctn.get_node_type(), __dp::CallTreeNodeType::Function); + ASSERT_EQ(ctn.get_iteration_id(), 0); + + ctn = __dp::CallTreeNode( nullptr, __dp::CallTreeNodeType::Function, 1, 1); + ASSERT_EQ(ctn.get_loop_or_function_id(), 1); + ASSERT_EQ(ctn.get_node_type(), __dp::CallTreeNodeType::Function); + ASSERT_EQ(ctn.get_iteration_id(), 0); + + ctn = __dp::CallTreeNode( nullptr, __dp::CallTreeNodeType::Loop, 2, 0); + ASSERT_EQ(ctn.get_loop_or_function_id(), 2); + ASSERT_EQ(ctn.get_node_type(), __dp::CallTreeNodeType::Loop); + ASSERT_EQ(ctn.get_iteration_id(), 0); + + ctn = __dp::CallTreeNode( nullptr, __dp::CallTreeNodeType::Loop, 2, 1); + ASSERT_EQ(ctn.get_loop_or_function_id(), 2); + ASSERT_EQ(ctn.get_node_type(), __dp::CallTreeNodeType::Loop); + ASSERT_EQ(ctn.get_iteration_id(), 0); + + ctn = __dp::CallTreeNode( nullptr, __dp::CallTreeNodeType::Iteration, 2, 1); + ASSERT_EQ(ctn.get_loop_or_function_id(), 2); + ASSERT_EQ(ctn.get_node_type(), __dp::CallTreeNodeType::Iteration); + ASSERT_EQ(ctn.get_iteration_id(), 1); +} + +TEST_F(CallTreeNodeTest, testGetParentPtr){ + auto root = __dp::CallTreeNode(); + auto function = __dp::CallTreeNode( make_shared<__dp::CallTreeNode>(root), __dp::CallTreeNodeType::Function, 1, 0); + auto loop = __dp::CallTreeNode( make_shared<__dp::CallTreeNode>(function), __dp::CallTreeNodeType::Loop, 2, 0); + auto iteration = __dp::CallTreeNode( make_shared<__dp::CallTreeNode>(loop), __dp::CallTreeNodeType::Iteration, 2, 1); + + ASSERT_EQ(iteration.get_parent_ptr()->get_node_type(), __dp::CallTreeNodeType::Loop); + ASSERT_EQ(iteration.get_parent_ptr()->get_loop_or_function_id(), 2); + ASSERT_EQ(iteration.get_parent_ptr()->get_iteration_id(), 0); + + ASSERT_EQ(iteration.get_parent_ptr()->get_parent_ptr()->get_node_type(), __dp::CallTreeNodeType::Function); + ASSERT_EQ(iteration.get_parent_ptr()->get_parent_ptr()->get_loop_or_function_id(), 1); + ASSERT_EQ(iteration.get_parent_ptr()->get_parent_ptr()->get_iteration_id(), 0); +} \ No newline at end of file diff --git a/test/unit_tests/calltree/metadata_queue/test_metadata_queue.cpp b/test/unit_tests/calltree/metadata_queue/test_metadata_queue.cpp new file mode 100644 index 000000000..1fd46b5ee --- /dev/null +++ b/test/unit_tests/calltree/metadata_queue/test_metadata_queue.cpp @@ -0,0 +1,8 @@ +#include + +#include "../../../../rtlib/calltree/MetaDataQueue.hpp" + +class MetaDataQueueTest : public ::testing::Test {}; + +TEST_F(MetaDataQueueTest, dummy) { +} \ No newline at end of file From 3fea67e0155725ea31c6d4e4791906450bb80622 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 3 Jul 2024 08:36:26 +0200 Subject: [PATCH 004/105] fix[merge conflicts]: renamed iFunctions -> runtimeFunctions --- rtlib/calltree/DependencyMetadata.hpp | 2 +- rtlib/calltree/MetaDataQueue.cpp | 2 +- rtlib/calltree/MetaDataQueueElement.hpp | 2 +- rtlib/calltree/utils.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rtlib/calltree/DependencyMetadata.hpp b/rtlib/calltree/DependencyMetadata.hpp index e00a7be16..669fc8799 100644 --- a/rtlib/calltree/DependencyMetadata.hpp +++ b/rtlib/calltree/DependencyMetadata.hpp @@ -13,7 +13,7 @@ #pragma once #include "../DPUtils.hpp" -#include "../iFunctionsTypes.hpp" +#include "../runtimeFunctionsTypes.hpp" #include "MetaDataQueueElement.hpp" namespace __dp diff --git a/rtlib/calltree/MetaDataQueue.cpp b/rtlib/calltree/MetaDataQueue.cpp index c49dd000b..61b13b8eb 100644 --- a/rtlib/calltree/MetaDataQueue.cpp +++ b/rtlib/calltree/MetaDataQueue.cpp @@ -13,7 +13,7 @@ #include "MetaDataQueue.hpp" #include "../../share/include/timer.hpp" -#include "../iFunctionsGlobals.hpp" +#include "../runtimeFunctionsGlobals.hpp" namespace __dp { diff --git a/rtlib/calltree/MetaDataQueueElement.hpp b/rtlib/calltree/MetaDataQueueElement.hpp index b77966fe4..a642aff0e 100644 --- a/rtlib/calltree/MetaDataQueueElement.hpp +++ b/rtlib/calltree/MetaDataQueueElement.hpp @@ -16,7 +16,7 @@ #include "CallTreeNode.hpp" #include #include -#include "../iFunctionsTypes.hpp" +#include "../runtimeFunctionsTypes.hpp" namespace __dp { diff --git a/rtlib/calltree/utils.cpp b/rtlib/calltree/utils.cpp index 28d6d1286..c330ade68 100644 --- a/rtlib/calltree/utils.cpp +++ b/rtlib/calltree/utils.cpp @@ -12,7 +12,7 @@ #include "utils.hpp" #include "../../share/include/timer.hpp" -#include "../iFunctionsGlobals.hpp" +#include "../runtimeFunctionsGlobals.hpp" #include namespace __dp{ From a9dc63649221c1d749cb1a1c859a0c5e20445399 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 3 Jul 2024 08:46:15 +0200 Subject: [PATCH 005/105] feat: update c++ version from 11 to 17 --- CMakeLists.txt | 2 +- rtlib/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 53fc5a5d5..809bed8a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ cmake_minimum_required(VERSION 3.4.3) project(DiscoPoP) -set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD 17) if (POLICY CMP0077) cmake_policy(SET CMP0077 NEW) diff --git a/rtlib/CMakeLists.txt b/rtlib/CMakeLists.txt index e3163137b..2d901e4d3 100644 --- a/rtlib/CMakeLists.txt +++ b/rtlib/CMakeLists.txt @@ -47,7 +47,7 @@ set(DiscoPoP_SOURCES ) set(CMAKE_CXX_FLAGS - "-O2 -std=c++11 -pthread -fno-rtti -fPIE -fPIC -ffreestanding") + "-O2 -std=c++17 -pthread -fno-rtti -fPIE -fPIC -ffreestanding") # add_custom_target(DiscoPoP) From 57efb835d5586a7530896e20da0598d179f7e474 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Mon, 8 Jul 2024 13:18:11 +0200 Subject: [PATCH 006/105] chore: refactor static analysis pass separated globals separated structs separated RegisterPass separate instrumentAlloca separate low-level instrumentation functions separate high-level instrumentation functions separate value initializations separated llvm hooks separate dp_reduction functions separate simple utility functions separate output functions separate variable name utilities move runOnFunction move runOnModule moved CFA moved utils moved CU creation moved take branch instrumentation finalized restructuring apply clang-format moved hybrid analysis fix: add license tags fixed test gold standard to match formatted code --- DiscoPoP/CMakeLists.txt | 57 +- DiscoPoP/DiscoPoP.cpp | 3698 +---------------- DiscoPoP/DiscoPoP.hpp | 168 +- DiscoPoP/Enums.hpp | 15 + DiscoPoP/Globals.cpp | 18 + DiscoPoP/Globals.hpp | 19 + DiscoPoP/RegisterPass.cpp | 33 + DiscoPoP/RegisterPass.hpp | 20 + DiscoPoP/Structs.hpp | 125 + DiscoPoP/dp_reduction/CFA.cpp | 123 + .../dp_reduction/determine_variable_name.cpp | 98 + .../dp_reduction/determine_variable_type.cpp | 52 + .../dp_reduction/find_reduction_instr.cpp | 40 + DiscoPoP/dp_reduction/get_load_instr.cpp | 79 + DiscoPoP/dp_reduction/get_reduction_instr.cpp | 50 + DiscoPoP/dp_reduction/get_var.cpp | 47 + DiscoPoP/dp_reduction/insert_functions.cpp | 73 + DiscoPoP/dp_reduction/utils.cpp | 236 ++ DiscoPoP/{ => hybrid_analysis}/Graph.hpp | 0 .../{ => hybrid_analysis}/InstructionCFG.cpp | 0 .../{ => hybrid_analysis}/InstructionCFG.hpp | 0 .../{ => hybrid_analysis}/InstructionDG.cpp | 0 .../{ => hybrid_analysis}/InstructionDG.hpp | 0 .../initialization/initializeBBDepCounter.cpp | 25 + .../initialization/initializeCUIDCounter.cpp | 24 + .../high_level/instrumentFunction.cpp | 31 + .../high_level/instrumentLoop.cpp | 212 + .../high_level/instrumentModule.cpp | 27 + .../low_level/insertDPFinalize.cpp | 20 + .../low_level/instrumentAlloca.cpp | 72 + .../low_level/instrumentCalloc.cpp | 49 + .../low_level/instrumentDeleteOrFree.cpp | 31 + .../low_level/instrumentFuncEntry.cpp | 103 + .../low_level/instrumentLoad.cpp | 65 + .../low_level/instrumentLoopEntry.cpp | 42 + .../low_level/instrumentLoopExit.cpp | 30 + .../low_level/instrumentNewOrMalloc.cpp | 49 + .../low_level/instrumentPosixMemalign.cpp | 49 + .../low_level/instrumentRealloc.cpp | 55 + .../low_level/instrumentStore.cpp | 65 + .../taken_branches/createInstrumentation.cpp | 50 + DiscoPoP/llvm_hooks/doFinalization.cpp | 61 + DiscoPoP/llvm_hooks/doInitialization.cpp | 121 + DiscoPoP/llvm_hooks/runOnBasicBlock.cpp | 257 ++ DiscoPoP/llvm_hooks/runOnFunction.cpp | 474 +++ DiscoPoP/llvm_hooks/runOnModule.cpp | 69 + DiscoPoP/static_analysis/createCUs.cpp | 344 ++ DiscoPoP/static_analysis/fillCUVariables.cpp | 73 + .../populateGlobalVariablesSet.cpp | 47 + DiscoPoP/utils/CFA.cpp | 118 + DiscoPoP/utils/output.cpp | 213 + DiscoPoP/utils/simple.cpp | 184 + DiscoPoP/utils/variables/defLine.cpp | 85 + DiscoPoP/utils/variables/names.cpp | 251 ++ DiscoPoP/utils/variables/types.cpp | 53 + rtlib/calltree/CallTree.cpp | 128 +- rtlib/calltree/CallTree.hpp | 27 +- rtlib/calltree/CallTreeNode.cpp | 86 +- rtlib/calltree/CallTreeNode.hpp | 29 +- rtlib/calltree/CallTreeNodeType.hpp | 7 +- rtlib/calltree/DependencyMetadata.cpp | 149 +- rtlib/calltree/DependencyMetadata.hpp | 70 +- rtlib/calltree/MetaDataQueue.cpp | 234 +- rtlib/calltree/MetaDataQueue.hpp | 47 +- rtlib/calltree/MetaDataQueueElement.cpp | 78 +- rtlib/calltree/MetaDataQueueElement.hpp | 63 +- rtlib/calltree/utils.cpp | 249 +- rtlib/calltree/utils.hpp | 4 +- rtlib/injected_functions/dp_finalize.cpp | 8 +- rtlib/injected_functions/dp_func_entry.cpp | 3 +- rtlib/injected_functions/dp_loop_entry.cpp | 6 +- rtlib/memory/PerfectShadow.hpp | 3 +- rtlib/runtimeFunctions.cpp | 185 +- rtlib/runtimeFunctions.hpp | 2 +- rtlib/runtimeFunctionsGlobals.cpp | 6 +- rtlib/runtimeFunctionsGlobals.hpp | 10 +- rtlib/runtimeFunctionsTypes.hpp | 9 +- share/include/timer.hpp | 11 +- .../do_all/calls/complex/src/code.cpp | 62 +- test/end_to_end/do_all/calls/complex/test.py | 2 +- .../src/code.cpp | 62 +- .../complex_no_varname_duplicates/test.py | 2 +- .../both_loops_doall/src/FileMapping.txt | 1 + .../calltree/call_tree/test_call_tree.cpp | 19 +- .../call_tree_node/test_call_tree_node.cpp | 28 +- .../metadata_queue/test_metadata_queue.cpp | 3 +- 86 files changed, 5264 insertions(+), 4629 deletions(-) create mode 100644 DiscoPoP/Enums.hpp create mode 100644 DiscoPoP/Globals.cpp create mode 100644 DiscoPoP/Globals.hpp create mode 100644 DiscoPoP/RegisterPass.cpp create mode 100644 DiscoPoP/RegisterPass.hpp create mode 100644 DiscoPoP/Structs.hpp create mode 100644 DiscoPoP/dp_reduction/CFA.cpp create mode 100644 DiscoPoP/dp_reduction/determine_variable_name.cpp create mode 100644 DiscoPoP/dp_reduction/determine_variable_type.cpp create mode 100644 DiscoPoP/dp_reduction/find_reduction_instr.cpp create mode 100644 DiscoPoP/dp_reduction/get_load_instr.cpp create mode 100644 DiscoPoP/dp_reduction/get_reduction_instr.cpp create mode 100644 DiscoPoP/dp_reduction/get_var.cpp create mode 100644 DiscoPoP/dp_reduction/insert_functions.cpp create mode 100644 DiscoPoP/dp_reduction/utils.cpp rename DiscoPoP/{ => hybrid_analysis}/Graph.hpp (100%) rename DiscoPoP/{ => hybrid_analysis}/InstructionCFG.cpp (100%) rename DiscoPoP/{ => hybrid_analysis}/InstructionCFG.hpp (100%) rename DiscoPoP/{ => hybrid_analysis}/InstructionDG.cpp (100%) rename DiscoPoP/{ => hybrid_analysis}/InstructionDG.hpp (100%) create mode 100644 DiscoPoP/initialization/initializeBBDepCounter.cpp create mode 100644 DiscoPoP/initialization/initializeCUIDCounter.cpp create mode 100644 DiscoPoP/instrumentation/high_level/instrumentFunction.cpp create mode 100644 DiscoPoP/instrumentation/high_level/instrumentLoop.cpp create mode 100644 DiscoPoP/instrumentation/high_level/instrumentModule.cpp create mode 100644 DiscoPoP/instrumentation/low_level/insertDPFinalize.cpp create mode 100644 DiscoPoP/instrumentation/low_level/instrumentAlloca.cpp create mode 100644 DiscoPoP/instrumentation/low_level/instrumentCalloc.cpp create mode 100644 DiscoPoP/instrumentation/low_level/instrumentDeleteOrFree.cpp create mode 100644 DiscoPoP/instrumentation/low_level/instrumentFuncEntry.cpp create mode 100644 DiscoPoP/instrumentation/low_level/instrumentLoad.cpp create mode 100644 DiscoPoP/instrumentation/low_level/instrumentLoopEntry.cpp create mode 100644 DiscoPoP/instrumentation/low_level/instrumentLoopExit.cpp create mode 100644 DiscoPoP/instrumentation/low_level/instrumentNewOrMalloc.cpp create mode 100644 DiscoPoP/instrumentation/low_level/instrumentPosixMemalign.cpp create mode 100644 DiscoPoP/instrumentation/low_level/instrumentRealloc.cpp create mode 100644 DiscoPoP/instrumentation/low_level/instrumentStore.cpp create mode 100644 DiscoPoP/instrumentation/taken_branches/createInstrumentation.cpp create mode 100644 DiscoPoP/llvm_hooks/doFinalization.cpp create mode 100644 DiscoPoP/llvm_hooks/doInitialization.cpp create mode 100644 DiscoPoP/llvm_hooks/runOnBasicBlock.cpp create mode 100644 DiscoPoP/llvm_hooks/runOnFunction.cpp create mode 100644 DiscoPoP/llvm_hooks/runOnModule.cpp create mode 100644 DiscoPoP/static_analysis/createCUs.cpp create mode 100644 DiscoPoP/static_analysis/fillCUVariables.cpp create mode 100644 DiscoPoP/static_analysis/populateGlobalVariablesSet.cpp create mode 100644 DiscoPoP/utils/CFA.cpp create mode 100644 DiscoPoP/utils/output.cpp create mode 100644 DiscoPoP/utils/simple.cpp create mode 100644 DiscoPoP/utils/variables/defLine.cpp create mode 100644 DiscoPoP/utils/variables/names.cpp create mode 100644 DiscoPoP/utils/variables/types.cpp create mode 100644 test/end_to_end/do_all/simple/nested/depth_2/positive/both_loops_doall/src/FileMapping.txt diff --git a/DiscoPoP/CMakeLists.txt b/DiscoPoP/CMakeLists.txt index abc5162c5..941b755cc 100644 --- a/DiscoPoP/CMakeLists.txt +++ b/DiscoPoP/CMakeLists.txt @@ -12,9 +12,62 @@ include_directories( add_llvm_library(LLVMDiscoPoP MODULE DiscoPoP.cpp - InstructionCFG.cpp - InstructionDG.cpp ../share/lib/DPUtils.cpp + + Globals.cpp + RegisterPass.cpp + + instrumentation/low_level/instrumentAlloca.cpp + instrumentation/low_level/instrumentNewOrMalloc.cpp + instrumentation/low_level/instrumentRealloc.cpp + instrumentation/low_level/instrumentCalloc.cpp + instrumentation/low_level/instrumentPosixMemalign.cpp + instrumentation/low_level/instrumentDeleteOrFree.cpp + instrumentation/low_level/instrumentLoad.cpp + instrumentation/low_level/instrumentStore.cpp + instrumentation/low_level/instrumentFuncEntry.cpp + instrumentation/low_level/instrumentLoopEntry.cpp + instrumentation/low_level/instrumentLoopExit.cpp + instrumentation/low_level/insertDPFinalize.cpp + + instrumentation/high_level/instrumentFunction.cpp + instrumentation/high_level/instrumentLoop.cpp + instrumentation/high_level/instrumentModule.cpp + + instrumentation/taken_branches/createInstrumentation.cpp + + initialization/initializeCUIDCounter.cpp + initialization/initializeBBDepCounter.cpp + + llvm_hooks/doInitialization.cpp + llvm_hooks/doFinalization.cpp + llvm_hooks/runOnBasicBlock.cpp + llvm_hooks/runOnFunction.cpp + llvm_hooks/runOnModule.cpp + + dp_reduction/get_load_instr.cpp + dp_reduction/find_reduction_instr.cpp + dp_reduction/determine_variable_name.cpp + dp_reduction/determine_variable_type.cpp + dp_reduction/CFA.cpp + dp_reduction/get_var.cpp + dp_reduction/get_reduction_instr.cpp + dp_reduction/utils.cpp + dp_reduction/insert_functions.cpp + + utils/simple.cpp + utils/output.cpp + utils/CFA.cpp + utils/variables/names.cpp + utils/variables/types.cpp + utils/variables/defLine.cpp + + static_analysis/createCUs.cpp + static_analysis/fillCUVariables.cpp + static_analysis/populateGlobalVariablesSet.cpp + + hybrid_analysis/InstructionCFG.cpp + hybrid_analysis/InstructionDG.cpp ) # forward compiler flags diff --git a/DiscoPoP/DiscoPoP.cpp b/DiscoPoP/DiscoPoP.cpp index 8bf8ea695..e231db5b3 100644 --- a/DiscoPoP/DiscoPoP.cpp +++ b/DiscoPoP/DiscoPoP.cpp @@ -16,14 +16,6 @@ #include "DiscoPoP.hpp" -#define DP_DEBUG false -#define DP_VERBOSE false // prints warning messages -#define DP_hybrid_DEBUG false -#define DP_BRANCH_TRACKING \ - true // toggles the creation of instrumentation calls for tracking taken - // branches. Required by the graph pruning step of the DiscoPoP - // optimizer. - using namespace llvm; using namespace std; using namespace dputil; @@ -86,162 +78,6 @@ void DiscoPoP::setupCallbacks() { ThisModule->getOrInsertFunction("__dp_incr_taken_branch_counter", Void, CharPtr, Int32, Int32); } -bool DiscoPoP::doInitialization(Module &M) { - if (DP_DEBUG) { - errs() << "DiscoPoP | 190: init pass DiscoPoP \n"; - } - - // prepare environment variables - char const *tmp = getenv("DOT_DISCOPOP"); - if (tmp == NULL) { - // DOT_DISCOPOP needs to be initialized - setenv("DOT_DISCOPOP", ".discopop", 1); - } - std::string tmp_str(getenv("DOT_DISCOPOP")); - setenv("DOT_DISCOPOP_PROFILER", (tmp_str + "/profiler").data(), 1); - - // prepare .discopop directory if not present - struct stat st1 = {0}; - if (stat(getenv("DOT_DISCOPOP"), &st1) == -1) { - mkdir(getenv("DOT_DISCOPOP"), 0777); - } - // prepare profiler directory if not present - struct stat st2 = {0}; - if (stat(getenv("DOT_DISCOPOP_PROFILER"), &st2) == -1) { - mkdir(getenv("DOT_DISCOPOP_PROFILER"), 0777); - } - - // prepare target directory if not present - char const *tmp2 = getenv("DP_PROJECT_ROOT_DIR"); - if (tmp2 == NULL) { - // DP_PROJECT_ROOT_DIR needs to be initialized - std::cerr << "\nWARNING: No value for DP_PROJECT_ROOT_DIR found. \n"; - std::cerr << " As a result, library functions might be " - "instrumented which can lead to\n"; - std::cerr << " increased profiling times and unexpected behavior.\n"; - std::cerr << " Please consider to specify the environment variable " - "and rebuild.\n"; - std::cerr << " " - "https://discopop-project.github.io/discopop/setup/" - "environment_variables/\n\n"; - // define fallback - setenv("DP_PROJECT_ROOT_DIR", "/", 1); - } - - // CUGeneration - { - CUIDCounter = 0; - defaultIsGlobalVariableValue = false; - ThisModule = &M; - outCUIDCounter = NULL; - - initializeCUIDCounter(); - - for (Module::global_iterator I = ThisModule->global_begin(); I != ThisModule->global_end(); I++) { - Value *globalVariable = dyn_cast(I); - string glo = string(globalVariable->getName()); - if (glo.find(".") == glo.npos) { - programGlobalVariablesSet.insert(glo); - // originalVariablesSet.insert(glo); - } - } - } - // CUGeneration end - - // DPInstrumentation - { - // Export M to the outside - ThisModule = &M; - ThisModuleContext = &(M.getContext()); - - for (set::iterator it = GlobalVars.begin(); it != GlobalVars.end(); ++it) { - GlobalVars.erase(it); - } - - GlobalVars.clear(); - Structs.clear(); - collectDebugInfo(); - - // Initialize variables needed - setupDataTypes(); - setupCallbacks(); - - // Check loop parallelism? - if (ClCheckLoopPar) { - if (DP_DEBUG) { - errs() << "check loop parallelism \n"; - } - loopID = 0; - } else { - loopID = -1; - } - } - // DPInstrumentation end - - // DPInstrumentationOmission - { - bbDepCount = 0; - - initializeBBDepCounter(); - - ReportBB = M.getOrInsertFunction("__dp_report_bb", Void, Int32); - ReportBBPair = M.getOrInsertFunction("__dp_report_bb_pair", Void, Int32, Int32); - VNF = new dputil::VariableNameFinder(M); - int nextFreeStaticMemoryRegionID = 0; - } - // DPInstrumentationOmission end - - return true; -} - -bool DiscoPoP::doFinalization(Module &M) { - // CUGeneration - - // write the current count of CUs to a file to avoid duplicate CUs. - outCUIDCounter = new std::ofstream(); - std::string tmp(getenv("DOT_DISCOPOP_PROFILER")); - tmp += "/DP_CUIDCounter.txt"; - outCUIDCounter->open(tmp.data(), std::ios_base::out); - if (outCUIDCounter && outCUIDCounter->is_open()) { - *outCUIDCounter << CUIDCounter; - outCUIDCounter->flush(); - outCUIDCounter->close(); - } - // CUGeneration end - - // DPInstrumentationOmission - for (Function &F : M) { - if (!F.hasName() || F.getName() != "main") - continue; - for (BasicBlock &BB : F) { - for (Instruction &I : BB) { - if (CallInst *call_inst = dyn_cast(&I)) { - if (Function *Fun = call_inst->getCalledFunction()) { - if (Fun->getName() == "__dp_finalize") { - IRBuilder<> builder(call_inst); - Value *V = builder.CreateGlobalStringPtr(StringRef(bbDepString), ".dp_bb_deps"); - CallInst::Create(F.getParent()->getOrInsertFunction("__dp_add_bb_deps", Void, CharPtr), V, "", call_inst); - } - } - } - } - } - } - // write the current count of BBs to a file to avoid duplicate BBids - outBBDepCounter = new std::ofstream(); - std::string tmp2(getenv("DOT_DISCOPOP_PROFILER")); - tmp2 += "/DP_BBDepCounter.txt"; - outBBDepCounter->open(tmp2.data(), std::ios_base::out); - if (outBBDepCounter && outBBDepCounter->is_open()) { - *outBBDepCounter << bbDepCount; - outBBDepCounter->flush(); - outBBDepCounter->close(); - } - - // DPInstrumentationOmission end - return true; -} - DiscoPoP::~DiscoPoP() { if (ocfg.is_open()) { ocfg.flush(); @@ -260,3514 +96,46 @@ void DiscoPoP::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); } -// CUGeneration - -void DiscoPoP::getFunctionReturnLines(Region *TopRegion, Node *root) { - int lid = 0; - for (Region::block_iterator bb = TopRegion->block_begin(); bb != TopRegion->block_end(); ++bb) { - for (BasicBlock::iterator instruction = (*bb)->begin(); instruction != (*bb)->end(); ++instruction) { - if (isa(instruction)) { - lid = getLID(&*instruction, fileID); - if (lid > 0) - root->returnLines.insert(lid); - } - } - } -} - -string DiscoPoP::determineVariableDefLine(Instruction *I) { - string varDefLine{"LineNotFound"}; - - bool isGlobal = false; - string varName = determineVariableName_static(&*I, isGlobal, true); - // varName = refineVarName(varName); - varName = (varName.find(".addr") == varName.npos) ? varName : varName.erase(varName.find(".addr"), 5); - // varName.erase(varName.find(".addr"), 5); - // size_t pos = varName.find(".addr"); - // if (pos != varName.npos) - // varName.erase(varName.find(".addr"), 5); - - string varType = determineVariableType(&*I); - - if (programGlobalVariablesSet.count(varName)) { - varDefLine = "GlobalVar"; - // Find definition line of global variables - GlobalVariable *globalVariable = I->getParent()->getParent()->getParent()->getGlobalVariable(StringRef(varName)); - if (globalVariable) { - MDNode *metadata = globalVariable->getMetadata("dbg"); - if (metadata) { - if (isa(metadata)) { - varDefLine = - to_string(fileID) + ":" + - to_string(cast(globalVariable->getMetadata("dbg"))->getVariable()->getLine()); - } - } - } - } - - // Start from the beginning of a function and look for the variable - Function *F = I->getFunction(); - for (Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) { - BasicBlock &BB = *FI; - for (BasicBlock::iterator BI = BB.begin(), E = BB.end(); BI != E; ++BI) { - if (DbgDeclareInst *DI = dyn_cast(BI)) { - - if (auto *N = dyn_cast(DI->getVariable())) { - if (auto *DV = dyn_cast(N)) { - if (varType.find("ARRAY") != string::npos || varType.find("STRUCT") != string::npos) { - if (DV->getName() == varName) { - varDefLine = to_string(fileID) + ":" + to_string(DV->getLine()); - break; - } - } else { - string vn = "----"; - bool isGlobal; - AllocaInst *AI = dyn_cast_or_null(DI->getAddress()); - if (AI) { - for (User *U : AI->users()) { - if (StoreInst *SI = dyn_cast(U)) { - vn = determineVariableName_static(&*SI, isGlobal, true); - break; - } else if (LoadInst *LI = dyn_cast(U)) { - vn = determineVariableName_static(&*LI, isGlobal, true); - break; - } - } - if (vn == varName || vn == varName + ".addr") { - varDefLine = to_string(fileID) + ":" + to_string(DV->getLine()); - break; - } - } - } - } - } - } - } - } - return varDefLine; -} - -string DiscoPoP::determineVariableType(Instruction *I) { - string s = ""; - string type_str; - int index = isa(I) ? 1 : 0; - raw_string_ostream rso(type_str); - (*((I->getOperand(index))->getType())).print(rso); - - Value *operand = I->getOperand(index); - - if (operand->hasName()) { - if (isa(*operand)) { - GetElementPtrInst *gep = cast(operand); - Value *ptrOperand = gep->getPointerOperand(); - PointerType *PTy = cast(ptrOperand->getType()); - // we've found a struct/class - Type *structType = pointsToStruct(PTy); - if (structType && gep->getNumOperands() > 2) { - s = "STRUCT,"; - } - - // we've found an array - if (PTy->getPointerElementType()->getTypeID() == Type::ArrayTyID) { - s = "ARRAY,"; - } else { - // check if previous instruction is a GEP as well. If so, an Array has - // been found (e.g. double**) - Value *prevInst = cast(gep)->getOperand(0); - if (isa(prevInst)) { - s = "ARRAY,"; - } else if (prevInst->getType()->isPointerTy()) { - s = "ARRAY,"; - } - } - } - } - - s = s + rso.str(); - return s; -} - -// recieves the region and outputs all variables and variables crossing basic -// block boundaries in the region. -void DiscoPoP::populateGlobalVariablesSet(Region *TopRegion, set &globalVariablesSet) { - - map variableToBBMap; - bool isGlobalVariable; - for (Region::block_iterator bb = TopRegion->block_begin(); bb != TopRegion->block_end(); ++bb) { - for (BasicBlock::iterator instruction = (*bb)->begin(); instruction != (*bb)->end(); ++instruction) { - if (isa(instruction) || isa(instruction) || isa(instruction)) { - - // NOTE: changed 'instruction' to '&*instruction' - string varName = determineVariableName_static(&*instruction, isGlobalVariable, false); - - if (isGlobalVariable) // add it if it is a global variable in the - // program - { - programGlobalVariablesSet.insert(varName); - } - - if (variableToBBMap.find(varName) != variableToBBMap.end()) { - // this var has already once recordded. check for bb id - if (variableToBBMap[varName] != *bb) { - // global variable found. Insert into the globalVariablesSet - globalVariablesSet.insert(varName); - } - } else { - // record usage of the variable. - variableToBBMap.insert(pair(varName, *bb)); - } - } - } - } -} - -void DiscoPoP::createTakenBranchInstrumentation(Region *TopRegion, map> &BBIDToCUIDsMap) { - /* Create calls to count taken branches inbetween CUs during execution */ - for (Region::block_iterator bb = TopRegion->block_begin(); bb != TopRegion->block_end(); ++bb) { - for (BasicBlock::iterator instruction = (*bb)->begin(); instruction != (*bb)->end(); ++instruction) { - if (isa(instruction)) { - BranchInst *branchInst = cast(instruction); - // check for conditional branches, as unconditional ones can be ignored - // for counting - if (!branchInst->isUnconditional()) { - // branchInst is conditional - // prepare IRBuilder to insert instrumentation - IRBuilder<> IRB(branchInst); - // get BBId and CU IDS of the source - string source_BBID = bb->getName().str(); - for (auto source_cu : BBIDToCUIDsMap[source_BBID]) { - // get BBIds of all targets - for (int i = 0; i < branchInst->getNumSuccessors(); i++) { - string successor_BBID = branchInst->getSuccessor(i)->getName().str(); - // get CUs of all targets - for (auto target_cu : BBIDToCUIDsMap[successor_BBID]) { - // add instrumentation prior to the branch instruction - vector args; - string source_and_target = source_cu->ID + ";" + target_cu->ID; - args.push_back(getOrInsertVarName_dynamic(source_and_target, IRB)); - args.push_back(branchInst->getCondition()); - bool counter_active_on_cmp_value = (i == 0 ? 1 : 0); - args.push_back(ConstantInt::get(Int32, counter_active_on_cmp_value)); - IRB.CreateCall(DpTakenBranchCounterIncr, args); - } - } - } - } - } - } - } -} - -void DiscoPoP::createCUs(Region *TopRegion, set &globalVariablesSet, vector &CUVector, - map> &BBIDToCUIDsMap, Node *root, LoopInfo &LI) { - const DataLayout *DL = &ThisModule->getDataLayout(); // used to get data size of variables, - // pointers, structs etc. - Node *currentNode = root; - CU *cu; - int lid; - string varName; - bool isGlobalVar = false; - string varType; - set suspiciousVariables; - string basicBlockName; - - map loopToNodeMap; - - for (Region::block_iterator bb = TopRegion->block_begin(); bb != TopRegion->block_end(); ++bb) { - - // Get the closest loop where bb lives in. - // (loop == NULL) if bb is not in any loop. - Loop *loop = LI.getLoopFor(*bb); - if (loop) { - // if bb is in a loop and if we have already created a node for that loop, - // assign it to currentNode. - if (loopToNodeMap.find(loop) != loopToNodeMap.end()) { - currentNode = loopToNodeMap[loop]; - } - // else, create a new Node for the loop, add it as children of currentNode - // and add it to the map. - else { - Node *n = new Node; - n->type = nodeTypes::loop; - n->parentNode = currentNode; - currentNode->childrenNodes.push_back(n); - - loopToNodeMap[loop] = n; - currentNode = n; - } - } else { - // end of loops. go to the parent of the loop. may have to jump several - // nodes in case of nested loops - for (map::iterator it = loopToNodeMap.begin(); it != loopToNodeMap.end(); it++) - if (it->second == currentNode) // current node found in loop map jump to its parent. - { - currentNode = currentNode->parentNode; - it = loopToNodeMap.begin(); // search the whole map again for current node - if (it->second == currentNode) // due to it++ we need to check first - // element of map ourself - currentNode = currentNode->parentNode; - } - } - - cu = new CU; - - if (bb->getName().size() == 0) - bb->setName(cu->ID); - - cu->BBID = bb->getName().str(); - cu->BB = *bb; - currentNode->childrenNodes.push_back(cu); - vector basicBlockCUVector; - basicBlockCUVector.push_back(cu); - BBIDToCUIDsMap.insert(pair>(bb->getName(), basicBlockCUVector)); - DILocalScope *scopeBuffer = NULL; - - for (BasicBlock::iterator instruction = (*bb)->begin(); instruction != (*bb)->end(); ++instruction) { - // NOTE: 'instruction' --> '&*instruction' - lid = getLID(&*instruction, fileID); - basicBlockName = bb->getName().str(); - - // Do not allow to combine Instructions from different scopes in the - // source code. - if ((&*instruction)->getDebugLoc()) { - if ((&*instruction)->getDebugLoc()->getScope() != scopeBuffer) { - // scopes are not equal - - int scopeIsParentOfBuffer = 0; - if (scopeBuffer) { - scopeIsParentOfBuffer = (&*instruction)->getDebugLoc()->getScope() == scopeBuffer->getScope(); - } - - if (scopeIsParentOfBuffer) { - // allow a combination of two CU's if the second scope is the parent - // of the first scope - } else { - // create a new CU. Do not allow to combine Instructions from - // different scopes in the source code. - - // create new CU if the old one contains any instruction - if ((!cu->readPhaseLineNumbers.empty()) || (!cu->writePhaseLineNumbers.empty()) || - (!cu->returnInstructions.empty())) { - cu->startLine = *(cu->instructionsLineNumbers.begin()); - cu->endLine = *(cu->instructionsLineNumbers.rbegin()); - - cu->basicBlockName = basicBlockName; - CUVector.push_back(cu); - suspiciousVariables.clear(); - CU *temp = cu; // keep current CU to make a reference to the successor CU - cu = new CU; - - cu->BBID = bb->getName().str(); - cu->BB = *bb; - - currentNode->childrenNodes.push_back(cu); - temp->successorCUs.push_back(cu->ID); - BBIDToCUIDsMap[bb->getName().str()].push_back(cu); - } - } - // update scopeBuffer - scopeBuffer = (&*instruction)->getDebugLoc()->getScope(); - } - } - - if (lid > 0) { - cu->instructionsLineNumbers.insert(lid); - cu->instructionsCount++; - // find return instructions - if (isa(instruction)) { - cu->returnInstructions.insert(lid); - } - // find branches to return instructions, i.e. return statements - else if (isa(instruction)) { - if ((cast(instruction))->isUnconditional()) { - if ((cast(instruction))->getNumSuccessors() == 1) { - BasicBlock *successorBB = (cast(instruction))->getSuccessor(0); - for (BasicBlock::iterator innerInstruction = successorBB->begin(); innerInstruction != successorBB->end(); - ++innerInstruction) { - if (isa(innerInstruction)) { - cu->returnInstructions.insert(lid); - break; - } - } - } - } - } - if (isa(instruction)) { - // get size of data written into memory by this store instruction - Value *operand = instruction->getOperand(1); - Type *Ty = operand->getType(); - unsigned u = DL->getTypeSizeInBits(Ty); - cu->writeDataSize += u; - varName = determineVariableName_static(&*instruction, isGlobalVar, false); - varType = determineVariableType(&*instruction); - suspiciousVariables.insert(varName); - if (lid > 0) - cu->writePhaseLineNumbers.insert(lid); - } else if (isa(instruction)) { - // get size of data read from memory by this load instruction - Type *Ty = instruction->getType(); - unsigned u = DL->getTypeSizeInBits(Ty); - cu->readDataSize += u; - varName = determineVariableName_static(&*instruction, isGlobalVar, false); - if (suspiciousVariables.count(varName)) { - // VIOLATION OF CAUTIOUS PROPERTY - // it is a load instruction which read the value of a global - // variable. - // This global variable has already been stored previously. - // A new CU should be created here. - cu->readPhaseLineNumbers.erase(lid); - cu->writePhaseLineNumbers.erase(lid); - cu->instructionsLineNumbers.erase(lid); - cu->instructionsCount--; - if (cu->instructionsLineNumbers.empty()) { - // cu->removeCU(); - cu->startLine = -1; - cu->endLine = -1; - } else { - cu->startLine = *(cu->instructionsLineNumbers.begin()); - cu->endLine = *(cu->instructionsLineNumbers.rbegin()); - } - cu->basicBlockName = basicBlockName; - CUVector.push_back(cu); - suspiciousVariables.clear(); - CU *temp = cu; // keep current CU to make a reference to the successor CU - cu = new CU; - - cu->BBID = bb->getName().str(); - cu->BB = *bb; - - currentNode->childrenNodes.push_back(cu); - temp->successorCUs.push_back(cu->ID); - BBIDToCUIDsMap[bb->getName().str()].push_back(cu); - if (lid > 0) { - cu->readPhaseLineNumbers.insert(lid); - cu->instructionsLineNumbers.insert(lid); - } - } else { - if (globalVariablesSet.count(varName) || programGlobalVariablesSet.count(varName)) { - if (lid > 0) - cu->readPhaseLineNumbers.insert(lid); - } - } - } else if (isa(instruction)) { - // get the name of the called function and check if a FileIO function - // is called - CallInst *ci = cast(instruction); - set IOFunctions{ - "fopen", "fopen_s", "freopen", "freopen_s", "fclose", "fflush", "setbuf", - "setvbuf", "fwide", "fread", "fwrite", "fgetc", "getc", "fgets", - "fputc", "putc", "fputs", "getchar", "gets", "gets_s", "putchar", - "puts", "ungetc", "fgetwc", "getwc", "fgetws", "fputwc", "putwc", - "fputws", "getwchar", "putwchar", "ungetwc", "scanf", "fscanf", "sscanf", - "scanf_s", "fscanf_s", "sscanf_s", "vscanf", "vfscanf", "vsscanf", "vscanf_s", - "vfscanf_s", "vsscanf_s", "printf", "fprintf", "sprintf", "snprintf", "printf_s", - "fprintf_s", "sprintf_s", "snprintf_s", "vprintf", "vfprintf", "vsprintf", "vsnprintf", - "vprintf_s", "vfprintf_s", "vsprintf_s", "vsnprintf_s", "wscanf", "fwscanf", "swscanf", - "wscanf_s", "fwscanf_s", "swscanf_s", "vwscanf", "vfwscanf", "vswscanf", "vwscanf_s", - "vfwscanf_s", "vswscanf_s", "wprintf", "fwprintf", "swprintf", "wprintf_s", "wprintf_s", - "swprintf_s", "snwprintf_s", "vwprintf", "vfwprintf", "vswprintf", "vwprintf_s", "vfwprintf_s", - "vswprintf_s", "vsnwprintf_s", "ftell", "fgetpos", "fseek", "fsetpos", "rewind", - "clearerr", "feof", "ferror", "perror", "remove", "rename", "tmpfile", - "tmpfile_s", "tmpnam", "tmpnam_s", "__isoc99_fscanf"}; - if (ci) { - if (ci->getCalledFunction()) { - if (ci->getCalledFunction()->hasName()) { - if (find(IOFunctions.begin(), IOFunctions.end(), ci->getCalledFunction()->getName().str()) != - IOFunctions.end()) { - // Called function performs FileIO - cu->performsFileIO = true; - } - } - } - } - } - } - } - if (cu->instructionsLineNumbers.empty()) { - // cu->removeCU(); - cu->startLine = -1; - cu->endLine = -1; - } else { - cu->startLine = *(cu->instructionsLineNumbers.begin()); - cu->endLine = *(cu->instructionsLineNumbers.rbegin()); - } - - cu->basicBlockName = basicBlockName; - CUVector.push_back(cu); - suspiciousVariables.clear(); - - // check for call instructions in current basic block - for (BasicBlock::iterator instruction = (*bb)->begin(); instruction != (*bb)->end(); ++instruction) { - // Note: Don't create nodes for library functions (c++/llvm). - LID lid = getLID(&*instruction, fileID); - if (lid > 0) { - if (isa(instruction)) { - CallInst *ci = cast(instruction); - Function *f = ci->getCalledFunction(); - // TODO: DO the same for Invoke inst - - string lid; - if (f) { - Function::iterator FI = f->begin(); - bool externalFunction = true; - for (Function::iterator FI = f->begin(), FE = f->end(); FI != FE; ++FI) { - externalFunction = false; - auto tempBI = FI->begin(); - if (DebugLoc dl = tempBI->getDebugLoc()) { - lid = to_string(dl->getLine()); - } else { - if (tempBI->getFunction()->getSubprogram()) - lid = to_string(tempBI->getFunction()->getSubprogram()->getLine()); - else { - lid = "LineNotFound"; - } - } - break; - } - if (externalFunction) - continue; - } else { - lid = "LineNotFound"; - } - - Node *n = new Node; - n->type = nodeTypes::dummy; - // For ordinary function calls, F has a name. - // However, sometimes the function being called - // in IR is encapsulated by "bitcast()" due to - // the way of compiling and linking. In this way, - // getCalledFunction() method returns NULL. - // Also, getName() returns NULL if this is an indirect function call. - if (f) { - n->name = f->getName().str(); - - // @Zia: This for loop appeared after the else part. For some - // function calls, the value of f is null. I guess that is why you - // have checked if f is not null here. Anyway, I (Mohammad) had to - // bring the for loop inside to avoid the segmentation fault. If you - // think it is not appropriate, find a solution for it. 14.2.2016 - for (Function::arg_iterator it = f->arg_begin(); it != f->arg_end(); it++) { - string type_str; - raw_string_ostream rso(type_str); - (it->getType())->print(rso); - Type *variableType = it->getType(); - while (variableType->isPointerTy()) { - variableType = variableType->getPointerElementType(); - } - Variable v(string(it->getName()), rso.str(), lid, true, true, - to_string(variableType->getScalarSizeInBits() / 8)); - n->argumentsList.push_back(v); - } - } else // get name of the indirect function which is called - { - Value *v = (cast(instruction))->getCalledOperand(); - Value *sv = v->stripPointerCasts(); - n->name = sv->getName().str(); - } - - // Recursive functions - CallGraphWrapperPass *CGWP = &(getAnalysis()); - if (isRecursive(*f, CGWP->getCallGraph())) { - int lid = getLID(&*instruction, fileID); - n->recursiveFunctionCall = n->name + " " + dputil::decodeLID(lid) + ","; - } - - vector BBCUsVector = BBIDToCUIDsMap[bb->getName().str()]; - // locate the CU where this function call belongs - for (auto i : BBCUsVector) { - int lid = getLID(&*instruction, fileID); - if (lid >= i->startLine && lid <= i->endLine) { - i->instructionsLineNumbers.insert(lid); - i->childrenNodes.push_back(n); - i->callLineTofunctionMap[lid].push_back(n); - break; - } - } - } - } - } - } -} - -void DiscoPoP::fillCUVariables(Region *TopRegion, set &globalVariablesSet, vector &CUVector, - map> &BBIDToCUIDsMap) { - int lid; - string varName, varType, varDefLine; - bool isGlobalVar = false; - // Changed TerminatorInst to Instuction - const Instruction *TInst; - string successorBB; - - for (Region::block_iterator bb = TopRegion->block_begin(); bb != TopRegion->block_end(); ++bb) { - CU *lastCU = BBIDToCUIDsMap[bb->getName().str()].back(); // get the last CU in the basic block - // get all successor basic blocks for bb - TInst = bb->getTerminator(); - for (unsigned i = 0, nSucc = TInst->getNumSuccessors(); i < nSucc; ++i) { - // get the name of successor basicBlock - successorBB = TInst->getSuccessor(i)->getName().str(); - // get the first CU of the successor basicBlock and record its ID in - // current CU's successorCUs - lastCU->successorCUs.push_back(BBIDToCUIDsMap[successorBB].front()->ID); - } - - auto bbCU = BBIDToCUIDsMap[bb->getName().str()].begin(); - for (BasicBlock::iterator instruction = (*bb)->begin(); instruction != (*bb)->end(); ++instruction) { - if (isa(instruction) || isa(instruction)) { - // NOTE: changed 'instruction' to '&*instruction' - lid = getLID(&*instruction, fileID); - if (lid == 0) - continue; - // NOTE: changed 'instruction' to '&*instruction', next 2 lines - varName = determineVariableName_static(&*instruction, isGlobalVar, false); - varType = determineVariableType(&*instruction); - - int index = isa(&*instruction) ? 1 : 0; - Type *variableType = (&*instruction)->getOperand(index)->getType(); - while (variableType->isPointerTy()) { - variableType = variableType->getPointerElementType(); - } - - string varSizeInBytes = to_string(variableType->getScalarSizeInBits() / 8); - - varDefLine = determineVariableDefLine(&*instruction); - - bool readAccess = isa(instruction); - bool writeAccess = isa(instruction); - - Variable v(varName, varType, varDefLine, readAccess, writeAccess, varSizeInBytes); - - if (lid > (*bbCU)->endLine) { - bbCU = next(bbCU, 1); - } - if (globalVariablesSet.count(varName) || programGlobalVariablesSet.count(varName)) { - (*bbCU)->globalVariableNames.insert(v); - } else { - (*bbCU)->localVariableNames.insert(v); - } - } - } - } -} - -void DiscoPoP::findStartEndLineNumbers(Node *root, int &start, int &end) { - if (root->type == nodeTypes::cu) { - if (start == -1 || start > root->startLine) { - start = root->startLine; - } - - if (end < root->endLine) { - end = root->endLine; - } - } - - for (auto i : root->childrenNodes) { - findStartEndLineNumbers(i, start, end); - } -} - -void DiscoPoP::fillStartEndLineNumbers(Node *root, LoopInfo &LI) { - if (root->type != nodeTypes::cu) { - int start = -1, end = -1; - - if (root->type == nodeTypes::loop) { - for (auto i : root->childrenNodes) { - if (i->type == nodeTypes::cu) { - Loop *loop = LI.getLoopFor(i->BB); - DebugLoc dl = loop->getStartLoc(); - LID lid = 0; - lid = (fileID << LIDSIZE) + dl->getLine(); - loopStartLines[root->ID] = dputil::decodeLID(lid); - break; - } - } - } - findStartEndLineNumbers(root, start, end); - - root->startLine = start; - root->endLine = end; - } - - for (auto i : root->childrenNodes) { - fillStartEndLineNumbers(i, LI); - } -} - -void DiscoPoP::initializeCUIDCounter() { - std::string CUCounterFile(getenv("DOT_DISCOPOP_PROFILER")); - CUCounterFile += "/DP_CUIDCounter.txt"; - if (dputil::fexists(CUCounterFile)) { - std::fstream inCUIDCounter(CUCounterFile, std::ios_base::in); - ; - inCUIDCounter >> CUIDCounter; - inCUIDCounter.close(); - } -} - -void DiscoPoP::initializeBBDepCounter() { - - std::string BBDepCounterFile(getenv("DOT_DISCOPOP_PROFILER")); - BBDepCounterFile += "/DP_BBDepCounter.txt"; - if (dputil::fexists(BBDepCounterFile)) { - std::fstream inBBDepCounter(BBDepCounterFile, std::ios_base::in); - ; - inBBDepCounter >> bbDepCount; - inBBDepCounter.close(); - } -} - -bool DiscoPoP::isRecursive(Function &F, CallGraph &CG) { - auto callNode = CG[&F]; - for (unsigned i = 0; i < callNode->size(); i++) { - if ((*callNode)[i]->getFunction() == &F) - return true; - } - return false; -} - -// CUGeneration end - -// DPReduction - -// iterates over all functions in the module and calls 'instrument_function' -// on suitable ones -void DiscoPoP::instrument_module(llvm::Module *module, map *trueVarNamesFromMetadataMap) { - for (llvm::Module::iterator func_it = module->begin(); func_it != module->end(); ++func_it) { - llvm::Function *func = &(*func_it); - std::string fn_name = func->getName().str(); - if (func->isDeclaration() || (strcmp(fn_name.c_str(), "NULL") == 0) || fn_name.find("llvm") != std::string::npos || - inlinedFunction(func)) { - continue; - } - instrument_function(func, trueVarNamesFromMetadataMap); - } -} - -bool DiscoPoP::inlinedFunction(Function *F) { - for (Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) { - for (BasicBlock::iterator BI = FI->begin(), E = FI->end(); BI != E; ++BI) { - if (DbgDeclareInst *DI = dyn_cast(BI)) { - if (DI->getDebugLoc()->getInlinedAt()) - return true; - } - } - } - return false; -} - -// iterates over all loops in a function and calls 'instrument_loop' for each -// one -void DiscoPoP::instrument_function(llvm::Function *function, map *trueVarNamesFromMetadataMap) { - - // get the corresponding file id - int32_t tmp_file_id; - determineFileID(*function, tmp_file_id); - if (tmp_file_id == 0) { - return; - } - - llvm::LoopInfo &loop_info = getAnalysis(*function).getLoopInfo(); - - for (auto loop_it = loop_info.begin(); loop_it != loop_info.end(); ++loop_it) { - instrument_loop(*function, tmp_file_id, *loop_it, loop_info, trueVarNamesFromMetadataMap); - } -} - -// Goes through all instructions in a loop and determines if they might be -// suitable for reduction. -// An entry is added to the 'loops_' vector and for each suitable instruction, -// an entry is added to the 'instructions_' vector. -void DiscoPoP::instrument_loop(Function &F, int file_id, llvm::Loop *loop, LoopInfo &LI, - map *trueVarNamesFromMetadataMap) { - - auto loc = loop->getStartLoc(); - if (!dp_reduction_loc_exists(loc)) { - return; - } +// DPReduction end - auto basic_blocks = loop->getBlocks(); - if (basic_blocks.size() < 3) { +void DiscoPoP::processStructTypes(string const &fullStructName, MDNode *structNode) { + assert(structNode && "structNode cannot be NULL"); + DIType *strDes = cast(structNode); + assert(strDes->getTag() == dwarf::DW_TAG_structure_type); + // sometimes it's impossible to get the list of struct members (e.g badref) + if (structNode->getNumOperands() <= 10 || structNode->getOperand(10) == NULL) { + errs() << "cannot process member list of this struct: \n"; + structNode->dump(); return; } - // add an entry to the 'loops_' vector - loop_info_t loop_info; - loop_info.line_nr_ = loc.getLine(); - loop_info.file_id_ = file_id; - loop_info.first_body_instr_ = &(*basic_blocks[1]->begin()); - - std::string loopEndLine = dp_reduction_CFA(F, loop, file_id); - loop_info.end_line = loopEndLine; - loop_info.function_name = string((basic_blocks[1]->getParent()->getName())); - loops_.push_back(loop_info); - - // call 'instrument_loop' on all its subloops - auto const sub_loops = loop->getSubLoops(); - for (auto loop_it = sub_loops.begin(); loop_it != sub_loops.end(); ++loop_it) { - instrument_loop(F, file_id, *loop_it, LI, trueVarNamesFromMetadataMap); - } - // The key corresponds to the variable that is loaded / stored. - // The value points to the actual load / store instruction. - std::map load_instructions; - std::map store_instructions; - - // Scan all instructions in the loop's basic blocks to find the load and - // store instructions. - for (size_t i = 0; i < basic_blocks.size(); ++i) { - llvm::BasicBlock *const bb = basic_blocks[i]; - - std::string bb_name = bb->getName().str(); - if ((std::strncmp("for.inc", bb_name.c_str(), 7) == 0) || (std::strncmp("for.cond", bb_name.c_str(), 8) == 0)) { - continue; - } - - for (auto instr_it = bb->begin(); instr_it != bb->end(); ++instr_it) { - llvm::Instruction *instr = &(*instr_it); - - auto opcode = instr->getOpcode(); - if (opcode != llvm::Instruction::Store && opcode != llvm::Instruction::Load) { - continue; - } - - // Add an entry to the corresponding map or invalidate an already - // existing entry, if the same instruction is executed on multiple - // lines. - llvm::Value *operand = dp_reduction_get_var(instr); - if (operand) { - std::map *map_ptr = - (opcode == llvm::Instruction::Store) ? &store_instructions : &load_instructions; - if (!map_ptr->insert(std::make_pair(operand, instr)).second) { - if ((*map_ptr)[operand]) { - llvm::DebugLoc new_loc = instr->getDebugLoc(); - llvm::DebugLoc old_loc = (*map_ptr)[operand]->getDebugLoc(); + Structs[fullStructName] = structNode; - if (!dp_reduction_loc_exists(new_loc) || !dp_reduction_loc_exists(old_loc)) { - (*map_ptr)[operand] = nullptr; - } else if (new_loc.getLine() != old_loc.getLine()) { - (*map_ptr)[operand] = nullptr; - } - } + MDNode *memberListNodes = cast(structNode->getOperand(10)); + for (unsigned i = 0; i < memberListNodes->getNumOperands(); ++i) { + assert(memberListNodes->getOperand(i)); + MDNode *member = cast(memberListNodes->getOperand(i)); + DINode *memberDes = cast(member); + // DIDescriptor memberDes(member); + if (memberDes->getTag() == dwarf::DW_TAG_member) { + assert(member->getOperand(9)); + MDNode *memberType = cast(member->getOperand(9)); + DIType *memberTypeDes = cast(memberType); + // DIType memberTypeDes(memberType); + if (memberTypeDes->getTag() == dwarf::DW_TAG_structure_type) { + string fullName = ""; + // try to get namespace + if (memberType->getNumOperands() > 2 && structNode->getOperand(2) != NULL) { + MDNode *namespaceNode = cast(structNode->getOperand(2)); + DINamespace *dins = cast(namespaceNode); + // DINameSpace dins(namespaceNode); + fullName = "struct." + string(dins->getName().data()) + "::"; } - } - } - } - - // only keep the instructions that satisfy the following conditions : - // - a variable that is read must also be written in the loop - // - a variable must not be read or written more than once - // - the store instruction comes after the load instruction - std::vector candidates; - for (auto it = load_instructions.begin(); it != load_instructions.end(); ++it) { - if (!it->second) - continue; - - auto it2 = store_instructions.find(it->first); - if (it2 != store_instructions.end() && it2->second) { - llvm::DebugLoc load_loc = it->second->getDebugLoc(); - llvm::DebugLoc store_loc = it2->second->getDebugLoc(); - if (!dp_reduction_loc_exists(load_loc) || !dp_reduction_loc_exists(store_loc)) - continue; - if (load_loc.getLine() > store_loc.getLine()) - continue; - if (load_loc.getLine() == loop_info.line_nr_ || store_loc.getLine() == loop_info.line_nr_) - continue; - - if (loop_info.end_line == "LOOPENDNOTFOUND") { - errs() << "WARNING: Loop end not found! File: " << file_id << " Function: " << F.getName() - << " Start line: " << loop_info.start_line << "\n"; - continue; - } - if (loop_info.line_nr_ > std::stoul(loop_info.end_line)) - continue; - - // Check if both load and store insts belong to the loop - if (load_loc.getLine() < loop_info.line_nr_ || load_loc.getLine() > std::stoul(loop_info.end_line)) - continue; - if (store_loc.getLine() < loop_info.line_nr_ || store_loc.getLine() > std::stoul(loop_info.end_line)) - continue; - - if (it->first->hasName()) { - instr_info_t info; - info.var_name_ = dp_reduction_determineVariableName(it->second, trueVarNamesFromMetadataMap); - info.loop_line_nr_ = loop_info.line_nr_; - info.file_id_ = file_id; - info.store_inst_ = llvm::dyn_cast(it2->second); - info.load_inst_ = llvm::dyn_cast(it->second); + // fullName += string(memberType->getOperand(3)->getName().data()); + fullName += (dyn_cast(memberType->getOperand(3)))->getString(); - candidates.push_back(info); + if (Structs.find(fullName) == Structs.end()) + processStructTypes(fullName, memberType); } } } - - // now check if the variables are part of a reduction operation - for (auto candidate : candidates) { - int index = isa(candidate.load_inst_) ? 1 : 0; - string varNameLoad = "LOAD"; - string varTypeLoad = "SCALAR"; - llvm::DebugLoc loc = (candidate.load_inst_)->getDebugLoc(); - - varNameLoad = dp_reduction_determineVariableName(candidate.load_inst_, trueVarNamesFromMetadataMap); - varTypeLoad = dp_reduction_determineVariableType(candidate.load_inst_); - if (llvm::isa(candidate.load_inst_->getOperand(index))) { - if (varTypeLoad.find("ARRAY,") == std::string::npos || varNameLoad.find(".addr") == std::string::npos || - varTypeLoad.find("**") != std::string::npos) { - continue; - } else if (varTypeLoad.find("ARRAY,") != std::string::npos || varNameLoad.find(".addr") != std::string::npos || - varTypeLoad.find("STRUCT,") != std::string::npos || varTypeLoad.find("**") != std::string::npos) { - llvm::Instruction *load_instr = nullptr; - llvm::Instruction *instr = dp_reduction_get_reduction_instr(candidate.store_inst_, &load_instr); - if (instr) { - candidate.load_inst_ = llvm::cast(load_instr); - candidate.operation_ = dp_reduction_get_char_for_opcode(instr); - } else { - continue; - } - } - } else { - if (varTypeLoad.find("ARRAY,") != std::string::npos || varNameLoad.find(".addr") != std::string::npos || - varTypeLoad.find("STRUCT,") != std::string::npos || varTypeLoad.find("**") != std::string::npos) { - llvm::Instruction *load_instr = nullptr; - llvm::Instruction *instr = dp_reduction_get_reduction_instr(candidate.store_inst_, &load_instr); - if (instr) { - candidate.load_inst_ = llvm::cast(load_instr); - candidate.operation_ = dp_reduction_get_char_for_opcode(instr); - } else { - // We should ignore store instructions that are not associated with a - // load e.g., pbvc[i] = c1s; - continue; - } - } else { - llvm::Instruction *load_instr = nullptr; - llvm::Instruction *instr = dp_reduction_get_reduction_instr(candidate.store_inst_, &load_instr); - if (instr) { - candidate.load_inst_ = llvm::cast(load_instr); - candidate.operation_ = dp_reduction_get_char_for_opcode(instr); - } else { - // We want to find max or min reduction operations - // We want to find the basicblock that contains the load instruction - // Then, we traverse the whole function to check if the reduction - // operation is > or < - BasicBlock *BB = (candidate.load_inst_)->getParent(); - string bbName = BB->getName().str(); - - // Ignore loops. Only look for conditional blocks - if (bbName.find("if") != std::string::npos || bbName.find("for") != std::string::npos) { - // e.g. in lulesh.cc: "if (domain.vdov(indx) != Real_t(0.)) { if ( - // dtf < dtcourant_tmp ) { dtcourant_tmp = dtf ; courant_elem = - // indx ; }}" - - // check if loaded value is used in the store instruction to prevent - // "false positives" - if (check_value_usage(candidate.store_inst_->getValueOperand(), cast(candidate.load_inst_))) { - candidate.operation_ = '>'; - } else { - continue; - } - } else { - continue; - } - } - } - } - instructions_.push_back(candidate); - } -} - -bool DiscoPoP::check_value_usage(llvm::Value *parentValue, llvm::Value *searchedValue) { - // Return true, if searchedValue is used within the computation of parentValue - if (parentValue == searchedValue) { - return true; - } - - // check operands recursively, if parentValue is not a constant yet - if (isa(parentValue)) { - return false; - } - // if parentValue is not an Instruction, the value can not be used, thus - // return false - if (!isa(parentValue)) { - errs() << "parentValue not an Instruction.\n"; - return false; - } - - llvm::Instruction *parentInstruction = cast(parentValue); - for (int idx = 0; idx < parentInstruction->getNumOperands(); idx++) { - if (check_value_usage(parentInstruction->getOperand(idx), searchedValue)) { - return true; - } - } - - return false; -} - -bool DiscoPoP::dp_reduction_init_util(std::string fmap_path) { - std::ifstream fmap_file; - fmap_file.open(fmap_path.c_str()); - if (fmap_file.fail()) { - std::cout << "Opening FileMapping failed: " << strerror(errno) << "\n"; - } - if (!fmap_file.is_open()) { - return false; - } - - std::string line; - while (std::getline(fmap_file, line)) { - char filename[512] = {'\0'}; - int file_id = 0; - - int cnt = sscanf(line.c_str(), "%d\t%s", &file_id, filename); - if (cnt == 2) { - - path_to_id_.emplace(std::string(filename), file_id); - } - } - - fmap_file.close(); - - return true; -} - -unsigned DiscoPoP::dp_reduction_get_file_id(llvm::Function *func) { - unsigned file_id = 0; - - // get the filepath of this function - char abs_path[PATH_MAX] = {'\0'}; - for (auto bb_it = func->begin(); bb_it != func->end(); ++bb_it) { - for (auto instr_it = bb_it->begin(); instr_it != bb_it->end(); ++instr_it) { - llvm::MDNode *node = instr_it->getMetadata("dbg"); - if (!node) - continue; - - llvm::DILocation *di_loc = llvm::dyn_cast(node); - llvm::StringRef filename = di_loc->getFilename(); - llvm::StringRef directory = di_loc->getDirectory(); - - char *success = realpath((directory.str() + "/" + filename.str()).c_str(), abs_path); - if (!success) { - realpath(filename.str().c_str(), abs_path); - } - - break; - } - if (abs_path[0] != '\0') - break; - } - - if (abs_path[0] != '\0') { - auto it = path_to_id_.find(std::string(abs_path)); - if (it != path_to_id_.end()) { - file_id = it->second; - } else { - } - } - - return file_id; -} - -// finds the previous use of 'val' -llvm::Instruction *DiscoPoP::dp_reduction_get_prev_use(llvm::Instruction *instr, llvm::Value *val) { - if (!instr) - return nullptr; - - auto instr_users = val->users(); - bool instr_found = false; - for (auto user : instr_users) { - if (!llvm::isa(user)) { - continue; - } - llvm::Instruction *usr_instr = llvm::cast(user); - - if (instr_found) { - return usr_instr; - } else if (usr_instr == instr) { - instr_found = true; - continue; - } - } - return llvm::dyn_cast(val); -} - -llvm::Value *DiscoPoP::dp_reduction_get_var_rec(llvm::Value *val) { - if (!val) - return nullptr; - - if (llvm::isa(val) || llvm::isa(val)) { - return val; - } - if (llvm::isa(val)) { - llvm::GetElementPtrInst *elem_ptr_instr = llvm::cast(val); - - // struct member reductions are not supported by OpenMP - llvm::Value *points_to = dp_reduction_points_to_var(elem_ptr_instr); - llvm::AllocaInst *a_instr = llvm::dyn_cast(points_to); - llvm::Type *type = (a_instr) ? a_instr->getAllocatedType() : points_to->getType(); - if (type->isStructTy()) { - return nullptr; - } - - return dp_reduction_get_var_rec(elem_ptr_instr->getPointerOperand()); - } - if (llvm::isa(val)) { - llvm::LoadInst *load_instr = llvm::cast(val); - return dp_reduction_get_var_rec(load_instr->getOperand(0)); - } - - return nullptr; -} - -// Get the value that is stored or loaded by a store / load instruction. -llvm::Value *DiscoPoP::dp_reduction_get_var(llvm::Instruction *instr) { - unsigned index = (llvm::isa(instr)) ? 0 : 1; - return dp_reduction_get_var_rec(instr->getOperand(index)); -} - -// Retrieves the reduction operation for the operand that is stored by the -// 'store_instr' (if such a reduction operation exists). -// The parameter 'load_instr' will point to the load instruction that actually -// loads the value (if such a load instruction exists). -llvm::Instruction *DiscoPoP::dp_reduction_get_reduction_instr(llvm::Instruction *store_instr, - llvm::Instruction **load_instr) { - // find the reduction operation for the source operand of the 'store_instr' - llvm::Instruction *reduction_instr = dp_reduction_find_reduction_instr(store_instr->getOperand(0)); - if (!reduction_instr) { - return nullptr; - } - // Now find the destination address of the store instruction. - // After that, search the load instruction that loads this value and store a - // pointer to it in 'load_instr'. - llvm::Value *store_dst = dp_reduction_get_var_rec(store_instr->getOperand(1)); - if (store_dst) { - std::vector reduction_operations; - *load_instr = dp_reduction_get_load_instr(store_dst, reduction_instr, reduction_operations); - // { *, / } > { +, - } > { & } > { ^ } > { | } - if (reduction_operations.size() > 1) { - int order = dp_reduction_get_op_order(reduction_operations[0]); - for (size_t i = 1; i != reduction_operations.size(); ++i) { - int order_i = dp_reduction_get_op_order(reduction_operations[i]); - if (order_i > order) { - *load_instr = nullptr; - return nullptr; - } - } - } - if (*load_instr) { - return reduction_instr; - } - } - - return nullptr; -} - -int DiscoPoP::dp_reduction_get_op_order(char c) { - if (c == '*' || c == '/') - return 5; - if (c == '+' || c == '-') - return 4; - if (c == '&') - return 3; - if (c == '^') - return 2; - if (c == '|') - return 1; - return 0; -} - -Type *DiscoPoP::dp_reduction_pointsToStruct(PointerType *PTy) { - assert(PTy); - Type *structType = PTy; - if (PTy->getTypeID() == Type::PointerTyID) { - while (structType->getTypeID() == Type::PointerTyID) { - structType = cast(structType)->getPointerElementType(); - } - } - return structType->getTypeID() == Type::StructTyID ? structType : NULL; -} - -string DiscoPoP::findStructMemberName_static(MDNode *structNode, unsigned idx, IRBuilder<> &builder) { - assert(structNode); - assert(structNode->getOperand(10)); - MDNode *memberListNodes = cast(structNode->getOperand(10)); - if (idx < memberListNodes->getNumOperands()) { - assert(memberListNodes->getOperand(idx)); - MDNode *member = cast(memberListNodes->getOperand(idx)); - if (member->getOperand(3)) { - getOrInsertVarName_static(dyn_cast(member->getOperand(3))->getString().str(), builder); - return dyn_cast(member->getOperand(3))->getString().str(); - } - } - return NULL; -} - -// returns the value that the GetElementPtrInst ultimately points to -llvm::Value *DiscoPoP::dp_reduction_points_to_var(llvm::GetElementPtrInst *instr) { - llvm::Value *points_to = nullptr; - while (instr) { - points_to = instr->getPointerOperand(); - instr = llvm::dyn_cast(points_to); - } - return points_to; -} - -// Finds the load instruction that actually loads the value from the address -// 'load_val'. -llvm::Instruction *DiscoPoP::dp_reduction_get_load_instr(llvm::Value *load_val, llvm::Instruction *cur_instr, - std::vector &reduction_operations) { - if (!load_val || !cur_instr) - return nullptr; - if (llvm::isa(cur_instr)) { - // Does the current instruction already load the value from the correct - // address? If that is the case, return it. - llvm::Value *val = cur_instr->getOperand(0); - if (val == load_val) - return cur_instr; - - // The current instruction does not load the value from the address of - // 'load_val'. But it might load the value from a variable where 'load_val' - // is stored in, so find the previous use of the source operand. - llvm::Instruction *prev_use = dp_reduction_get_prev_use(cur_instr, val); - if (prev_use) { - if (llvm::isa(prev_use)) { - return dp_reduction_get_load_instr(load_val, prev_use, reduction_operations); - } else if (llvm::isa(prev_use)) { - llvm::GetElementPtrInst *ptr_instr = llvm::cast(prev_use); - llvm::Value *points_to = dp_reduction_points_to_var(ptr_instr); - if (points_to == load_val) { - return cur_instr; - } else { - bool found = static_cast(dp_reduction_get_load_instr( - load_val, llvm::dyn_cast(points_to), reduction_operations)); - return (found) ? cur_instr : nullptr; - } - } else { - bool found = static_cast(dp_reduction_get_load_instr(load_val, prev_use, reduction_operations)); - return (found) ? cur_instr : nullptr; - } - } else { - return nullptr; - } - } - - unsigned opcode = cur_instr->getOpcode(); - char c = dp_reduction_get_char_for_opcode(cur_instr); - if (c != ' ') { - reduction_operations.push_back(c); - } - - // The current instruction is not a load instruction. Follow the operands - // of the current instruction recursively until the desired load instruction - // is reached. - llvm::Instruction *result = nullptr; - for (unsigned int i = 0; i != cur_instr->getNumOperands(); ++i) { - llvm::Value *operand = cur_instr->getOperand(i); - if (llvm::isa(operand)) { - result = dp_reduction_get_load_instr(load_val, llvm::cast(operand), reduction_operations); - if (result) { - break; - } - } - } - - if (!result && c != ' ') { - reduction_operations.pop_back(); - } - - return result; -} - -// returns the reduction instruction where 'val' is the operand if it can find -// such an operation -llvm::Instruction *DiscoPoP::dp_reduction_find_reduction_instr(llvm::Value *val) { - if (!val || !llvm::isa(val)) { - return nullptr; - } - llvm::Instruction *instr = llvm::cast(val); - unsigned opcode = instr->getOpcode(); - char c = dp_reduction_get_char_for_opcode(instr); - if (c != ' ') { - return instr; - } else if (opcode == llvm::Instruction::Load) { - llvm::Instruction *prev_use = dp_reduction_get_prev_use(instr, instr->getOperand(0)); - return dp_reduction_find_reduction_instr(prev_use); - } else if (opcode == llvm::Instruction::Store) { - return dp_reduction_find_reduction_instr(instr->getOperand(0)); - } - // enter recursion if the instruction has only a single operand to accomodate - // for type conversions etc. - if (instr->getNumOperands() == 1) { - // unpack instruction - return dp_reduction_find_reduction_instr(instr->getOperand(0)); - } - // no reduction instruction found - return nullptr; -} - -string DiscoPoP::dp_reduction_determineVariableName(Instruction *I, map *trueVarNamesFromMetadataMap) { - - assert(I && "Instruction cannot be NULL \n"); - int index = isa(I) ? 1 : 0; - Value *operand = I->getOperand(index); - - IRBuilder<> builder(I); - - if (operand == NULL) { - string retVal = getOrInsertVarName_static("", builder); - if (trueVarNamesFromMetadataMap->find(retVal) == trueVarNamesFromMetadataMap->end()) { - return retVal; // not found - } else { - return (*trueVarNamesFromMetadataMap)[retVal]; // found - } - } - - if (operand->hasName()) { - //// we've found a global variable - if (isa(*operand)) { - string retVal = string(operand->getName()); - if (trueVarNamesFromMetadataMap->find(retVal) == trueVarNamesFromMetadataMap->end()) { - return retVal; // not found - } else { - return (*trueVarNamesFromMetadataMap)[retVal]; // found - } - } - if (isa(*operand)) { - GetElementPtrInst *gep = cast(operand); - Value *ptrOperand = gep->getPointerOperand(); - PointerType *PTy = cast(ptrOperand->getType()); - - // we've found a struct/class - Type *structType = dp_reduction_pointsToStruct(PTy); - if (structType && gep->getNumOperands() > 2) { - Value *constValue = gep->getOperand(2); - if (constValue && isa(*constValue)) { - ConstantInt *idxPtr = cast(gep->getOperand(2)); - uint64_t memberIdx = *(idxPtr->getValue().getRawData()); - if (!(cast(structType))->isLiteral()) { - string strName(structType->getStructName().data()); - map::iterator it = Structs.find(strName); - if (it != Structs.end()) { - std::string ret = findStructMemberName_static(it->second, memberIdx, builder); - if (ret.size() > 0) { - string retVal = ret; - if (trueVarNamesFromMetadataMap->find(retVal) == trueVarNamesFromMetadataMap->end()) { - return retVal; // not found - } else { - return (*trueVarNamesFromMetadataMap)[retVal]; // found - } - } else { - string retVal = getOrInsertVarName_static("", builder); - if (trueVarNamesFromMetadataMap->find(retVal) == trueVarNamesFromMetadataMap->end()) { - return retVal; // not found - } else { - return (*trueVarNamesFromMetadataMap)[retVal]; // found - } - } - } - } - } - } - - // we've found an array - if (PTy->getPointerElementType()->getTypeID() == Type::ArrayTyID && isa(*ptrOperand)) { - return dp_reduction_determineVariableName((Instruction *)ptrOperand, trueVarNamesFromMetadataMap); - } - return dp_reduction_determineVariableName((Instruction *)gep, trueVarNamesFromMetadataMap); - } - string retVal = string(operand->getName().data()); - if (trueVarNamesFromMetadataMap->find(retVal) == trueVarNamesFromMetadataMap->end()) { - return retVal; // not found - } else { - return (*trueVarNamesFromMetadataMap)[retVal]; // found - } - } - - if (isa(*operand) || isa(*operand)) { - return dp_reduction_determineVariableName((Instruction *)(operand), trueVarNamesFromMetadataMap); - } - // if we cannot determine the name, then return * - return "*"; -} - -string DiscoPoP::dp_reduction_determineVariableType(Instruction *I) { - string s = ""; - string type_str; - int index = isa(I) ? 1 : 0; - raw_string_ostream rso(type_str); - (*((I->getOperand(index))->getType())).print(rso); - - Value *operand = I->getOperand(index); - - if (operand->hasName()) { - if (isa(*operand)) { - GetElementPtrInst *gep = cast(operand); - Value *ptrOperand = gep->getPointerOperand(); - PointerType *PTy = cast(ptrOperand->getType()); - // we've found a struct/class - Type *structType = dp_reduction_pointsToStruct(PTy); - if (structType && gep->getNumOperands() > 2) { - s = "STRUCT,"; - } - // we've found an array - if (PTy->getPointerElementType()->getTypeID() == Type::ArrayTyID) { - s = "ARRAY,"; - } else { - // check if previous instruction is a GEP aswell. If so, an Array has - // been found (e.g. double**) - Value *prevInst = cast(gep)->getOperand(0); - if (isa(prevInst)) { - s = "ARRAY,"; - } else if (prevInst->getType()->isPointerTy()) { - s = "ARRAY,"; - } - } - } - } - - s = s + rso.str(); - return s; -} - -std::string DiscoPoP::dp_reduction_CFA(Function &F, llvm::Loop *L, int file_id) { - std::string lid = "LOOPENDNOTFOUND"; - SmallVector ExitBlocks; - for (Function::iterator BB = F.begin(), BE = F.end(); BB != BE; ++BB) { - BasicBlock *tmpBB = &*BB; - ExitBlocks.clear(); - - // Get the closest loop where tmpBB lives in. - // (L == NULL) if tmpBB is not in any loop. - - // Check if tmpBB is the loop header (.cond) block. - if (L != NULL) { - StringRef loopType = tmpBB->getName().split('.').first; - - // If tmpBB is the header block, get the exit blocks of the loop. - if (L->hasDedicatedExits()) { - // loop exits are in canonical form - L->getUniqueExitBlocks(ExitBlocks); - } else { - // loop exits are NOT in canonical form - L->getExitBlocks(ExitBlocks); - } - - if (ExitBlocks.size() == 0) { - continue; - } - - // When loop has break statement inside, exit blocks may contain - // the if-else block containing the break. Since we always want - // to find the real exit (.end) block, we need to check the - // successors of the break statement(s). - SmallVector RealExitBlocks; - - for (SmallVectorImpl::iterator EI = ExitBlocks.begin(), END = ExitBlocks.end(); EI != END; ++EI) { - StringRef exitType = (*EI)->getName().split('.').first; - if (exitType.equals(loopType) && ((*EI)->getName().find("end") != string::npos) && - (std::find(RealExitBlocks.begin(), RealExitBlocks.end(), *EI) == RealExitBlocks.end())) { - RealExitBlocks.push_back(*EI); - } else { - // Changed TerminatorInst to Instruction - Instruction *TI = (*EI)->getTerminator(); - assert(TI != NULL && "Exit block is not well formed!"); - unsigned int numSucc = TI->getNumSuccessors(); - for (unsigned int i = 0; i < numSucc; ++i) { - BasicBlock *succ = TI->getSuccessor(i); - exitType = succ->getName().split('.').first; - if (exitType.equals(loopType) && (succ->getName().find("end") != string::npos) && - (std::find(RealExitBlocks.begin(), RealExitBlocks.end(), succ) == RealExitBlocks.end())) { - RealExitBlocks.push_back(succ); - } - } - } - } - - if (RealExitBlocks.size() == 0) { - continue; - } - - // Check if entry block and exit block(s) have valid LID. - bool hasValidExit = false; - for (SmallVectorImpl::iterator EI = RealExitBlocks.begin(), END = RealExitBlocks.end(); EI != END; - ++EI) { - hasValidExit = dp_reduction_sanityCheck(*EI, file_id); - if (hasValidExit == true) - break; - } - - if (hasValidExit) { - for (SmallVectorImpl::iterator EI = RealExitBlocks.begin(), END = RealExitBlocks.end(); EI != END; - ++EI) { - BasicBlock *currentBB = *EI; - vector args; - LID lid = 0; - - for (BasicBlock::iterator BI = currentBB->begin(), EI = currentBB->end(); BI != EI; ++BI) { - lid = dp_reduction_getLID(&*BI, file_id); - uint64_t ulid = (uint64_t)lid; - if (ulid != 0) { - return to_string(ulid % 16384); - } - } - } - } - } - } - if (lid == "LOOPENDNOTFOUND") { - if (MDNode *LoopID = L->getLoopID()) { - DebugLoc Start; - // We use the first DebugLoc in the header as the start location of the - // loop and if there is a second DebugLoc in the header we use it as end - // location of the loop. - bool foundEnd = false; - for (unsigned i = 1, ie = LoopID->getNumOperands(); i < ie; ++i) { - if (DILocation *DIL = dyn_cast(LoopID->getOperand(i))) { - if (!Start) { - if (foundEnd) { - lid = to_string(DebugLoc(DIL)->getLine()); - - break; - } else { - foundEnd = true; - } - } - } - } - } - } - return lid; -} - -// Encode the fileID and line number of BI as LID. -// This is needed to support multiple files in a project. -LID DiscoPoP::dp_reduction_getLID(Instruction *BI, int32_t &fileID) { - int32_t lno; - - const DebugLoc &location = BI->getDebugLoc(); - if (location) { - lno = BI->getDebugLoc().getLine(); - } else { - lno = 0; - } - - if (lno == 0) { - return 0; - } - LID lid = lno; - return lid; -} - -bool DiscoPoP::dp_reduction_sanityCheck(BasicBlock *BB, int file_id) { - LID lid; - for (BasicBlock::iterator BI = BB->begin(), EI = BB->end(); BI != EI; ++BI) { - lid = dp_reduction_getLID(&*BI, file_id); - if (lid > 0) { - return true; - } - } - return false; -} - -// returns a char describing the opcode, e.g. '+' for Add or FAdd -// switches + and - if a negative constant is added or subtracted -//(mainly used to support -- as reduction operation, might be implemented as -//'add -1') -char DiscoPoP::dp_reduction_get_char_for_opcode(llvm::Instruction *instr) { - unsigned opcode = instr->getOpcode(); - - if (opcode == llvm::Instruction::Add || opcode == llvm::Instruction::FAdd) { - bool operand_is_negative_constant = false; - if (instr->getNumOperands() >= 1) { - Value *rhs_value = instr->getOperand(1); - if (isa(rhs_value)) { - operand_is_negative_constant = cast(rhs_value)->isNegative(); - } - } - - if (operand_is_negative_constant) - return '-'; - else - return '+'; - } - if (opcode == llvm::Instruction::Sub || opcode == llvm::Instruction::FSub) { - bool operand_is_negative_constant = false; - if (instr->getNumOperands() >= 1) { - Value *rhs_value = instr->getOperand(1); - if (isa(rhs_value)) { - operand_is_negative_constant = cast(rhs_value)->isNegative(); - } - } - - if (operand_is_negative_constant) - return '+'; - else - return '-'; - } - if (opcode == llvm::Instruction::Mul || opcode == llvm::Instruction::FMul) - return '*'; - if (opcode == llvm::Instruction::And) - return '&'; - if (opcode == llvm::Instruction::Or) - return '|'; - if (opcode == llvm::Instruction::Xor) - return '^'; - return ' '; -} - -// return true if 'operand' is an operand of the instruction 'instr' -bool DiscoPoP::dp_reduction_is_operand(llvm::Instruction *instr, llvm::Value *operand) { - unsigned num_operands = instr->getNumOperands(); - for (unsigned i = 0; i < num_operands; ++i) { - if (instr->getOperand(i) == operand) - return true; - } - return false; -} - -// Inserts calls to allow for dynamic analysis of the loops. -void DiscoPoP::dp_reduction_insert_functions() { - - // insert function calls to monitor the variable's load and store operations - for (auto const &instruction : instructions_) { - int store_line = instruction.store_inst_->getDebugLoc().getLine(); - - // output information about the reduction variables - *reduction_file << " FileID : " << instruction.file_id_; - *reduction_file << " Loop Line Number : " << instruction.loop_line_nr_; - *reduction_file << " Reduction Line Number : " << to_string(store_line); - *reduction_file << " Variable Name : " << instruction.var_name_; - *reduction_file << " Operation Name : " << instruction.operation_ << "\n"; - } - - // insert function calls to monitor loop iterations - std::ofstream loop_metadata_file; - std::string tmp(getenv("DOT_DISCOPOP_PROFILER")); - tmp += "/loop_meta.txt"; - loop_metadata_file.open(tmp.data()); - int loop_id = 1; - llvm::Type *loop_incr_fn_arg_type = llvm::Type::getInt32Ty(*ctx_); - llvm::ArrayRef loop_incr_fn_args(loop_incr_fn_arg_type); - llvm::FunctionType *loop_incr_fn_type = - llvm::FunctionType::get(llvm::Type::getVoidTy(*ctx_), loop_incr_fn_args, false); - FunctionCallee incr_loop_counter_callee = module_->getOrInsertFunction("__dp_loop_incr", loop_incr_fn_type); - - for (auto const &loop_info : loops_) { - llvm::Value *val = llvm::ConstantInt::get(llvm::Type::getInt32Ty(*ctx_), loop_id); - llvm::ArrayRef args(val); - llvm::CallInst::Create(incr_loop_counter_callee, args, "", loop_info.first_body_instr_); - loop_metadata_file << loop_info.file_id_ << " "; - loop_metadata_file << loop_id++ << " "; - loop_metadata_file << loop_info.line_nr_ << "\n"; - } - loop_metadata_file.close(); - - // add a function to output the final data - // dp_loop_output - llvm::FunctionType *output_fn_type = llvm::FunctionType::get(llvm::Type::getVoidTy(*ctx_), false); - FunctionCallee loop_counter_output_callee = module_->getOrInsertFunction("__dp_loop_output", output_fn_type); - FunctionCallee cu_taken_branch_counter_output_callee = - module_->getOrInsertFunction("__dp_taken_branch_counter_output", output_fn_type); - llvm::Function *main_fn = module_->getFunction("main"); - if (main_fn) { - for (auto it = llvm::inst_begin(main_fn); it != llvm::inst_end(main_fn); ++it) { - if (llvm::isa(&(*it))) { - llvm::IRBuilder<> ir_builder(&(*it)); - ir_builder.CreateCall(loop_counter_output_callee); - if (DP_BRANCH_TRACKING) { - ir_builder.CreateCall(cu_taken_branch_counter_output_callee); - } - break; - } - } - } else { - llvm::errs() << "Warning : Could not find a main function\n"; - } -} - -// DPReduction end - -// Helper functions -bool DiscoPoP::isaCallOrInvoke(Instruction *BI) { - return (BI != NULL) && ((isa(BI) && (!isa(BI))) || isa(BI)); -} - -bool DiscoPoP::sanityCheck(BasicBlock *BB) { - LID lid; - for (BasicBlock::iterator BI = BB->begin(), EI = BB->end(); BI != EI; ++BI) { - lid = getLID(&*BI, fileID); - if (lid > 0) { - return true; - } - } - if (DP_VERBOSE) { - errs() << "WARNING: basic block " << BB << " doesn't contain valid LID.\n"; - } - return false; -} - -// Control-flow analysis functions - -void DiscoPoP::CFA(Function &F, LoopInfo &LI) { - SmallVector ExitBlocks; - for (Function::iterator BB = F.begin(), BE = F.end(); BB != BE; ++BB) { - BasicBlock *tmpBB = &*BB; - ExitBlocks.clear(); - - // Get the closest loop where tmpBB lives in. - // (L == NULL) if tmpBB is not in any loop. - Loop *L = LI.getLoopFor(tmpBB); - - // Check if tmpBB is the loop header (.cond) block. - if (L != NULL && LI.isLoopHeader(tmpBB)) { - StringRef loopType = tmpBB->getName().split('.').first; - if (DP_DEBUG) { - errs() << "loop [" << loopType << "] header: " << tmpBB->getName() << "\n"; - } - - // If tmpBB is the header block, get the exit blocks of the loop. - if (L->hasDedicatedExits()) { - // loop exits are in canonical form - L->getUniqueExitBlocks(ExitBlocks); - } else { - // loop exits are NOT in canonical form - L->getExitBlocks(ExitBlocks); - } - - if (ExitBlocks.size() == 0) { - errs() << "WARNING: loop at " << tmpBB << " is ignored: exit BB not found.\n"; - continue; - } - - // When loop has break statement inside, exit blocks may contain - // the if-else block containing the break. Since we always want - // to find the real exit (.end) block, we need to check the - // successors of the break statement(s). - SmallVector RealExitBlocks; - if (DP_DEBUG) { - errs() << "loop exits:"; - } - for (SmallVectorImpl::iterator EI = ExitBlocks.begin(), END = ExitBlocks.end(); EI != END; ++EI) { - StringRef exitType = (*EI)->getName().split('.').first; - if (exitType.equals(loopType) && ((*EI)->getName().find("end") != string::npos) && - (std::find(RealExitBlocks.begin(), RealExitBlocks.end(), *EI) == RealExitBlocks.end())) { - RealExitBlocks.push_back(*EI); - if (DP_DEBUG) { - errs() << " " << (*EI)->getName(); - } - } else { - // Changed TerminatorInst to Instruction - Instruction *TI = (*EI)->getTerminator(); - assert(TI != NULL && "Exit block is not well formed!"); - unsigned int numSucc = TI->getNumSuccessors(); - for (unsigned int i = 0; i < numSucc; ++i) { - BasicBlock *succ = TI->getSuccessor(i); - exitType = succ->getName().split('.').first; - if (exitType.equals(loopType) && (succ->getName().find("end") != string::npos) && - (std::find(RealExitBlocks.begin(), RealExitBlocks.end(), succ) == RealExitBlocks.end())) { - RealExitBlocks.push_back(succ); - if (DP_DEBUG) { - errs() << " " << succ->getName(); - } - } - } - } - } - if (DP_DEBUG) { - errs() << "\n"; - } - - // assert((RealExitBlocks.size() == 1) && "Loop has more than one real - // exit block!"); - if (RealExitBlocks.size() == 0) { - if (DP_VERBOSE) { - errs() << "WARNING: loop at " << tmpBB << " is ignored: exit blocks are not well formed.\n"; - } - continue; - } - - // Check if entry block and exit block(s) have valid LID. - bool hasValidEntry = sanityCheck(tmpBB); - bool hasValidExit = false; - for (SmallVectorImpl::iterator EI = RealExitBlocks.begin(), END = RealExitBlocks.end(); EI != END; - ++EI) { - hasValidExit = sanityCheck(*EI); - if (hasValidExit == true) - break; - } - - if (hasValidEntry && hasValidExit) { - // Instrument loop header block. - instrumentLoopEntry(tmpBB, loopID); - - // Instrument loop exit block(s). - for (SmallVectorImpl::iterator EI = RealExitBlocks.begin(), END = RealExitBlocks.end(); EI != END; - ++EI) { - instrumentLoopExit(*EI, loopID); - } - ++loopID; - } - } - } -} - -// pass get invoked here -bool DiscoPoP::runOnModule(Module &M) { - // cout << "MODULE " << M.getName().str() << "\n"; - - long counter = 0; - // cout << "\tFUNCTION:\n"; - for (Function &F : M) { - /* - string to_be_printed = "\t(" + to_string(++counter) + " / " + - to_string(M.size()) + ") -- " + F.getName().str(); - while(to_be_printed.size() < 100){ - to_be_printed += " "; - } - cout << to_be_printed + "\r"; - */ - runOnFunction(F); - } - - // DPReduction - module_ = &M; - ctx_ = &module_->getContext(); - - reduction_file = new std::ofstream(); - std::string tmp(getenv("DOT_DISCOPOP_PROFILER")); - tmp += "/reduction.txt"; - reduction_file->open(tmp.data(), std::ios_base::app); - - loop_counter_file = new std::ofstream(); - std::string tmp2(getenv("DOT_DISCOPOP_PROFILER")); - tmp2 += "/loop_counter_output.txt"; - loop_counter_file->open(tmp2.data(), std::ios_base::app); - - /* - bool success = dp_reduction_init_util(FileMappingPath); - if (!success) { - llvm::errs() << "could not find the FileMapping file: " << FileMappingPath - << "\n"; return false; - } - */ - instrument_module(&M, &trueVarNamesFromMetadataMap); - - dp_reduction_insert_functions(); - - if (reduction_file != NULL && reduction_file->is_open()) { - reduction_file->flush(); - reduction_file->close(); - } - - if (loop_counter_file != NULL && loop_counter_file->is_open()) { - loop_counter_file->flush(); - loop_counter_file->close(); - } - // End DPReduction - return true; -} - -bool DiscoPoP::runOnFunction(Function &F) { - if (DP_DEBUG) { - errs() << "pass DiscoPoP: run pass on function " << F.getName().str() << "\n"; - } - - // avoid instrumenting functions which are defined outside the scope of the - // project - std::string dp_project_dir(getenv("DP_PROJECT_ROOT_DIR")); - SmallVector, 4> MDs; - F.getAllMetadata(MDs); - bool funcDefinedInProject = false; - for (auto &MD : MDs) { - if (MDNode *N = MD.second) { - if (auto *subProgram = dyn_cast(N)) { - std::string fullFileName = ""; - if (subProgram->getDirectory().str().length() > 0) { - fullFileName += subProgram->getDirectory().str(); - fullFileName += "/"; - } - fullFileName += subProgram->getFilename().str(); - if (fullFileName.find(dp_project_dir) != string::npos) // function defined inside project - { - funcDefinedInProject = true; - } - } - } - } - if (!funcDefinedInProject) { - return false; - } - - StringRef funcName = F.getName(); - // Avoid functions we don't want to instrument - if (funcName.find("llvm.") != string::npos) // llvm debug calls - { - return false; - } - if (funcName.find("__dp_") != string::npos) // instrumentation calls - { - return false; - } - if (funcName.find("__cx") != string::npos) // c++ init calls - { - return false; - } - if (funcName.find("__clang") != string::npos) // clang helper calls - { - return false; - } - if (funcName.find("_GLOBAL_") != string::npos) // global init calls (c++) - { - return false; - } - if (funcName.find("pthread_") != string::npos) { - return false; - } - - vector CUVector; - set globalVariablesSet; // list of variables which appear in more than - // one basic block - map> BBIDToCUIDsMap; - - determineFileID(F, fileID); - - // only instrument functions belonging to project source files - if (!fileID) - return false; - - // CUGeneration - { - /********************* Initialize root values ***************************/ - Node *root = new Node; - root->name = F.getName().str(); - root->type = nodeTypes::func; - - // Get list of arguments for this function and store them in root. - // NOTE: changed the way we get the arguments - BasicBlock *BB = &F.getEntryBlock(); - auto BI = BB->begin(); - string lid; - if (DebugLoc dl = BI->getDebugLoc()) { - lid = to_string(dl->getLine()); - } else { - lid = to_string(BI->getFunction()->getSubprogram()->getLine()); - } - - for (Function::arg_iterator it = F.arg_begin(); it != F.arg_end(); it++) { - string type_str; - raw_string_ostream rso(type_str); - (it->getType())->print(rso); - Type *variableType = it->getType(); - while (variableType->isPointerTy()) { - variableType = variableType->getPointerElementType(); - } - Variable v(it->getName().str(), rso.str(), to_string(fileID) + ":" + lid, true, true, - to_string(variableType->getScalarSizeInBits() / 8)); - root->argumentsList.push_back(v); - } - /********************* End of initialize root values - * ***************************/ - LoopInfo &LI = getAnalysis(F).getLoopInfo(); - - // get the top level region - RIpass = &getAnalysis(F); - RI = &(RIpass->getRegionInfo()); - Region *TopRegion = RI->getTopLevelRegion(); - - getTrueVarNamesFromMetadata(TopRegion, root, &trueVarNamesFromMetadataMap); - - getFunctionReturnLines(TopRegion, root); - - populateGlobalVariablesSet(TopRegion, globalVariablesSet); - - createCUs(TopRegion, globalVariablesSet, CUVector, BBIDToCUIDsMap, root, LI); - - if (DP_BRANCH_TRACKING) { - createTakenBranchInstrumentation(TopRegion, BBIDToCUIDsMap); - } - - fillCUVariables(TopRegion, globalVariablesSet, CUVector, BBIDToCUIDsMap); - - fillStartEndLineNumbers(root, LI); - - secureStream(); - - // printOriginalVariables(originalVariablesSet); - - printData(root); - - for (auto i : CUVector) { - delete (i); - } - } - // CUGeneration end - - // DPInstrumentation - { - // Check loop parallelism? - if (ClCheckLoopPar) { - LoopInfo &LI = getAnalysis(F).getLoopInfo(); - CFA(F, LI); - } - - // Instrument the entry of the function. - // Each function entry is instrumented, and the first - // executed function will initialize shadow memory. - // See the definition of __dp_func_entry() for detail. - instrumentFuncEntry(F); - - // Traverse all instructions, collect loads/stores/returns, check for calls. - for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) { - BasicBlock &BB = *FI; - runOnBasicBlock(BB); - } - - if (DP_DEBUG) { - errs() << "pass DiscoPoP: finished function\n"; - } - } - // DPInstrumentation end - - // DPInstrumentationOmission - { - if (F.getInstructionCount() == 0) - return false; - -// Enable / Disable hybrid profiling -#ifndef DP_HYBRID_PROFILING -#define DP_HYBRID_PROFILING 1 -#endif - -#if DP_HYBRID_PROFILING == 0 - return true; -#endif - ///// - - if (DP_hybrid_DEBUG) - errs() << "\n---------- Omission Analysis on " << F.getName() << " ----------\n"; - - DebugLoc dl; - Value *V; - - set omittableInstructions; - - set staticallyPredictableValues; - // Get local values (variables) - for (Instruction &I : F.getEntryBlock()) { - if (AllocaInst *AI = dyn_cast(&I)) { - staticallyPredictableValues.insert(AI); - } - } - for (BasicBlock &BB : F) { - for (Instruction &I : BB) { - // Remove from staticallyPredictableValues those which are passed to - // other functions (by ref/ptr) - if (CallInst *call_inst = dyn_cast(&I)) { - if (Function *Fun = call_inst->getCalledFunction()) { - if (Fun->getName() == "__dp_write" || Fun->getName() == "__dp_read" || Fun->getName() == "__dp_alloca") { - ++totalInstrumentations; - } - for (uint i = 0; i < call_inst->getNumOperands() - 1; ++i) { - V = call_inst->getArgOperand(i); - std::set::iterator it = staticallyPredictableValues.find(V); - if (it != staticallyPredictableValues.end()) { - staticallyPredictableValues.erase(V); - if (DP_hybrid_DEBUG) - errs() << VNF->getVarName(V) << "\n"; - } - } - } - } - // Remove values from locals if dereferenced - if (isa(I)) { - V = I.getOperand(0); - for (Value *w : staticallyPredictableValues) { - if (w == V) { - staticallyPredictableValues.erase(V); - } - } - } - } - } - - // assign static memory region IDs to statically predictable values and thus - // dependencies - unordered_map> staticValueNameToMemRegIDMap; // : (original variable - // name, statically assigned MemReg ID) - bool tmpIsGlobal; - long next_id; - string llvmIRVarName; - string originalVarName; - string staticMemoryRegionID; - for (auto V : staticallyPredictableValues) { - next_id = nextFreeStaticMemoryRegionID++; - llvmIRVarName = VNF->getVarName(V); - // Note: Using variables names as keys is only possible at this point, - // since the map is created for each function individually. Thus, we can - // rely on the SSA properties of LLVM IR and can assume that e.g. scoping - // is handled by LLVM and destinct variable names are introduced. - originalVarName = trueVarNamesFromMetadataMap[llvmIRVarName]; - if (originalVarName.size() == 0) { - // no original variable name could be identified using the available - // metadata. Fall back to the LLVM IR name of the value. - originalVarName = llvmIRVarName; - } - staticMemoryRegionID = "S" + to_string(next_id); - staticValueNameToMemRegIDMap[llvmIRVarName] = pair(originalVarName, staticMemoryRegionID); - } - - if (DP_hybrid_DEBUG) { - errs() << "--- Local Values ---\n"; - for (auto V : staticallyPredictableValues) { - errs() << VNF->getVarName(V) << "\n"; - } - } - - // Perform the SPA dependence analysis - int32_t fid; - determineFileID(F, fid); - map> conditionalBBDepMap; - map>> conditionalBBPairDepMap; - - auto &DT = getAnalysis(F).getDomTree(); - InstructionCFG CFG(VNF, F); - InstructionDG DG(VNF, &CFG, fid); - - for (auto edge : DG.getEdges()) { - Instruction *Src = edge->getSrc()->getItem(); - Instruction *Dst = edge->getDst()->getItem(); - - V = Src->getOperand(isa(Src) ? 1 : 0); - if (isa(Dst)) - V = dyn_cast(Dst); - - if (staticallyPredictableValues.find(V) == staticallyPredictableValues.end()) - continue; - - if (Src != Dst && DT.dominates(Dst, Src)) { - if (!conditionalBBDepMap.count(Src->getParent())) { - set tmp; - conditionalBBDepMap[Src->getParent()] = tmp; - } - conditionalBBDepMap[Src->getParent()].insert(DG.edgeToDPDep(edge, staticValueNameToMemRegIDMap)); - } else { - if (!conditionalBBPairDepMap.count(Dst->getParent())) { - map> tmp; - conditionalBBPairDepMap[Dst->getParent()] = tmp; - } - if (!conditionalBBPairDepMap[Dst->getParent()].count(Src->getParent())) { - set tmp; - conditionalBBPairDepMap[Dst->getParent()][Src->getParent()] = tmp; - } - conditionalBBPairDepMap[Dst->getParent()][Src->getParent()].insert( - DG.edgeToDPDep(edge, staticValueNameToMemRegIDMap)); - } - omittableInstructions.insert(Src); - omittableInstructions.insert(Dst); - } - - // Omit SPA instructions with no dependences - for (auto node : DG.getInstructionNodes()) { - if (!isa(node->getItem()) && !!isa(node->getItem())) - continue; - V = node->getItem()->getOperand(isa(node->getItem()) ? 1 : 0); - if (!DG.getInEdges(node).size() && !DG.getOutEdges(node).size() && - staticallyPredictableValues.find(V) != staticallyPredictableValues.end()) - omittableInstructions.insert(node->getItem()); - } - - // Add observation of execution of single basic blocks - for (auto pair : conditionalBBDepMap) { - // Insert call to reportbb - Instruction *insertionPoint = pair.first->getTerminator(); - if (isa(pair.first->getTerminator())) { - insertionPoint = insertionPoint->getPrevNonDebugInstruction(); - } - auto CI = CallInst::Create(ReportBB, ConstantInt::get(Int32, bbDepCount), "", insertionPoint); - - // ---- Insert deps into string ---- - if (bbDepCount) - bbDepString += "/"; - bool first = true; - bbDepString += to_string(bbDepCount) + "="; - for (auto dep : pair.second) { - if (!first) - bbDepString += ","; - bbDepString += dep; - first = false; - } - // --------------------------------- - ++bbDepCount; - } - - // Add observation of in-order execution of pairs of basic blocks - for (auto pair1 : conditionalBBPairDepMap) { - // Alloca and init semaphore var for BB - auto AI = new AllocaInst(Int32, 0, "__dp_bb", F.getEntryBlock().getFirstNonPHI()->getNextNonDebugInstruction()); - new StoreInst(ConstantInt::get(Int32, 0), AI, false, AI->getNextNonDebugInstruction()); - - for (auto pair2 : pair1.second) { - // Insert check for semaphore - Instruction *insertionPoint = pair2.first->getTerminator(); - if (isa(pair2.first->getTerminator())) - insertionPoint = insertionPoint->getPrevNonDebugInstruction(); - - auto LI = new LoadInst(Int32, AI, Twine(""), false, insertionPoint); - ArrayRef arguments({LI, ConstantInt::get(Int32, bbDepCount)}); - CallInst::Create(ReportBBPair, arguments, "", insertionPoint); - - // ---- Insert deps into string ---- - if (bbDepCount) - bbDepString += "/"; - bbDepString += to_string(bbDepCount); - bbDepString += "="; - bool first = true; - for (auto dep : pair2.second) { - if (!first) - bbDepString += ","; - bbDepString += dep; - first = false; - } - // ---------------------------------- - ++bbDepCount; - } - // Insert semaphore update to true - new StoreInst(ConstantInt::get(Int32, 1), AI, false, pair1.first->getTerminator()); - } - - if (DumpToDot) { - CFG.dumpToDot(fileName + "_" + string(F.getName()) + ".CFG.dot"); - DG.dumpToDot(fileName + "_" + string(F.getName()) + ".DG.dot"); - } - - if (DP_hybrid_DEBUG) { - errs() << "--- Conditional BB Dependences:\n"; - for (auto pair : conditionalBBDepMap) { - errs() << pair.first->getName() << ":\n"; - for (auto s : pair.second) { - errs() << "\t" << s << "\n"; - } - } - - errs() << "--- Conditional BB-Pair Dependences:\n"; - for (auto pair1 : conditionalBBPairDepMap) { - for (auto pair2 : pair1.second) { - errs() << pair1.first->getName() << "-"; - errs() << pair2.first->getName() << ":\n"; - for (auto s : pair2.second) - errs() << "\t" << s << "\n"; - } - } - } - - if (DP_hybrid_DEBUG) { - errs() << "--- Program Instructions:\n"; - for (BasicBlock &BB : F) { - for (Instruction &I : BB) { - if (!isa(I) && !isa(I) && !isa(I)) - continue; - errs() << "\t" << (isa(I) ? "Write " : (isa(I) ? "Alloca " : "Read ")) << " | "; - if (dl = I.getDebugLoc()) { - errs() << dl.getLine() << "," << dl.getCol(); - } else { - errs() << F.getSubprogram()->getLine() << ",*"; - } - errs() << " | "; - V = I.getOperand(isa(I) ? 1 : 0); - if (isa(I)) { - V = dyn_cast(&I); - } - errs() << VNF->getVarName(V); - - if (omittableInstructions.find(&I) != omittableInstructions.end()) { - errs() << " | OMITTED"; - } - errs() << "\n"; - } - } - } - - // Remove omittable instructions from profiling - Instruction *DP_Instrumentation; - for (Instruction *I : omittableInstructions) { - if (isa(I)) { - DP_Instrumentation = I->getNextNode()->getNextNode(); - } else { - DP_Instrumentation = I->getPrevNode(); - } - - if (!DP_Instrumentation) - continue; - if (CallInst *call_inst = dyn_cast(DP_Instrumentation)) { - if (Function *Fun = call_inst->getCalledFunction()) { - string fn = Fun->getName().str(); - if (fn == "__dp_write" || fn == "__dp_read" || fn == "__dp_alloca") { - DP_Instrumentation->eraseFromParent(); - ++removedInstrumentations; - } - } - } - } - - // Report statically identified dependencies - - staticDependencyFile = new std::ofstream(); - std::string tmp(getenv("DOT_DISCOPOP_PROFILER")); - tmp += "/static_dependencies.txt"; - staticDependencyFile->open(tmp.data(), std::ios_base::app); - - for (auto pair : conditionalBBDepMap) { - for (auto s : pair.second) { - *staticDependencyFile << s << "\n"; - } - } - staticDependencyFile->flush(); - staticDependencyFile->close(); - - if (DP_hybrid_DEBUG) - errs() << "Done with function " << F.getName() << ":\n"; - } - // DPInstrumentationOmission end - return true; -} - -void DiscoPoP::collectDebugInfo() { - if (NamedMDNode *CU_Nodes = ThisModule->getNamedMetadata("llvm.dbg.cu")) { - for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { - DICompileUnit *CU = cast(CU_Nodes->getOperand(i)); - auto GVs = CU->getGlobalVariables(); - for (unsigned i = 0, e = GVs.size(); i < e; ++i) { - DIGlobalVariable *DIG = GVs[i]->getVariable(); - if (DIG) { - GlobalVars.insert(DIG); - } - } - } - } -} - -DIGlobalVariable *DiscoPoP::findDbgGlobalDeclare(GlobalVariable *v) { - assert(v && "Global variable cannot be null"); - for (set::iterator it = GlobalVars.begin(); it != GlobalVars.end(); ++it) { - if ((*it)->getDisplayName() == v->getName()) - return *it; - } - return NULL; -} - -string DiscoPoP::getOrInsertVarName_static(string varName, IRBuilder<> &builder) { - Value *valName = NULL; - std::string vName = varName; - map::iterator pair = VarNames.find(varName); - if (pair == VarNames.end()) { - valName = builder.CreateGlobalStringPtr(StringRef(varName.c_str()), ".str"); - - VarNames[varName] = valName; - } else { - vName = pair->first; - } - - return vName; -} - -Value *DiscoPoP::getOrInsertVarName_dynamic(string varName, IRBuilder<> &builder) { - // 26.08.2022 Lukas - // update varName with original varName from Metadata - if (trueVarNamesFromMetadataMap.find(varName) == trueVarNamesFromMetadataMap.end()) { - // not found, do nothing - } else { - // found, update varName - varName = trueVarNamesFromMetadataMap[varName]; - } - - Value *vName = NULL; - map::iterator pair = VarNames.find(varName); - if (pair == VarNames.end()) { - vName = builder.CreateGlobalStringPtr(StringRef(varName.c_str()), ".str"); - VarNames[varName] = vName; - } else { - vName = pair->second; - } - return vName; -} - -Value *DiscoPoP::findStructMemberName(MDNode *structNode, unsigned idx, IRBuilder<> &builder) { - assert(structNode); - assert(structNode->getOperand(10)); - MDNode *memberListNodes = cast(structNode->getOperand(10)); - if (idx < memberListNodes->getNumOperands()) { - assert(memberListNodes->getOperand(idx)); - MDNode *member = cast(memberListNodes->getOperand(idx)); - if (member->getOperand(3)) { - return getOrInsertVarName_dynamic(dyn_cast(member->getOperand(3))->getString().str(), builder); - } - } - return NULL; -} - -Type *DiscoPoP::pointsToStruct(PointerType *PTy) { - assert(PTy); - Type *structType = PTy; - if (PTy->getTypeID() == Type::PointerTyID) { - while (structType->getTypeID() == Type::PointerTyID) { - structType = cast(structType)->getElementType(); - } - } - return structType->getTypeID() == Type::StructTyID ? structType : NULL; -} - -string DiscoPoP::determineVariableName_static(Instruction *I, bool &isGlobalVariable /*=defaultIsGlobalVariableValue*/, - bool disable_MetadataMap) { - - assert(I && "Instruction cannot be NULL \n"); - int index = isa(I) ? 1 : 0; - Value *operand = I->getOperand(index); - - IRBuilder<> builder(I); - - if (operand == NULL) { - string retVal = getOrInsertVarName_static("", builder); - if (trueVarNamesFromMetadataMap.find(retVal) == trueVarNamesFromMetadataMap.end() || disable_MetadataMap) { - return retVal; // not found - } else { - return trueVarNamesFromMetadataMap[retVal]; // found - } - } - - if (operand->hasName()) { - //// we've found a global variable - if (isa(*operand)) { - // MOHAMMAD ADDED THIS FOR CHECKING - isGlobalVariable = true; - string retVal = string(operand->getName()); - if (trueVarNamesFromMetadataMap.find(retVal) == trueVarNamesFromMetadataMap.end() || disable_MetadataMap) { - return retVal; // not found - } else { - return trueVarNamesFromMetadataMap[retVal]; // found - } - } - if (isa(*operand)) { - GetElementPtrInst *gep = cast(operand); - Value *ptrOperand = gep->getPointerOperand(); - PointerType *PTy = cast(ptrOperand->getType()); - - // we've found a struct/class - Type *structType = pointsToStruct(PTy); - if (structType && gep->getNumOperands() > 2) { - Value *constValue = gep->getOperand(2); - if (constValue && isa(*constValue)) { - ConstantInt *idxPtr = cast(gep->getOperand(2)); - uint64_t memberIdx = *(idxPtr->getValue().getRawData()); - if (!(cast(structType))->isLiteral()) { - string strName(structType->getStructName().data()); - map::iterator it = Structs.find(strName); - if (it != Structs.end()) { - std::string ret = findStructMemberName_static(it->second, memberIdx, builder); - if (ret.size() > 0) { - string retVal = ret; - if (trueVarNamesFromMetadataMap.find(retVal) == trueVarNamesFromMetadataMap.end() || - disable_MetadataMap) { - return retVal; // not found - } else { - return trueVarNamesFromMetadataMap[retVal]; // found - } - } else { - string retVal = getOrInsertVarName_static("", builder); - if (trueVarNamesFromMetadataMap.find(retVal) == trueVarNamesFromMetadataMap.end() || - disable_MetadataMap) { - return retVal; // not found - } else { - return trueVarNamesFromMetadataMap[retVal]; // found - } - // return ret; - } - } - } - } - } - - // we've found an array - if (PTy->getPointerElementType()->getTypeID() == Type::ArrayTyID && isa(*ptrOperand)) { - return determineVariableName_static((Instruction *)ptrOperand, isGlobalVariable, false); - } - return determineVariableName_static((Instruction *)gep, isGlobalVariable, false); - } - string retVal = string(operand->getName().data()); - if (trueVarNamesFromMetadataMap.find(retVal) == trueVarNamesFromMetadataMap.end() || disable_MetadataMap) { - return retVal; // not found - } else { - return trueVarNamesFromMetadataMap[retVal]; // found - } - // return getOrInsertVarName(string(operand->getName().data()), builder); - } - - if (isa(*operand) || isa(*operand)) { - return determineVariableName_static((Instruction *)(operand), isGlobalVariable, false); - } - // if we cannot determine the name, then return * - return ""; // getOrInsertVarName("*", builder); -} - -Value *DiscoPoP::determineVariableName_dynamic(Instruction *const I) { - assert(I && "Instruction cannot be NULL \n"); - int index = isa(I) ? 1 : 0; - Value *operand = I->getOperand(index); - - IRBuilder<> builder(I); - - if (operand == NULL) { - return getOrInsertVarName_dynamic("*", builder); - } - - if (operand->hasName()) { - // we've found a global variable - if (isa(*operand)) { - DIGlobalVariable *gv = findDbgGlobalDeclare(cast(operand)); - if (gv != NULL) { - return getOrInsertVarName_dynamic(string(gv->getDisplayName().data()), builder); - } - } - if (isa(*operand)) { - GetElementPtrInst *gep = cast(operand); - Value *ptrOperand = gep->getPointerOperand(); - PointerType *PTy = cast(ptrOperand->getType()); - - // we've found a struct/class - Type *structType = pointsToStruct(PTy); - if (structType && gep->getNumOperands() > 2) { - Value *constValue = gep->getOperand(2); - if (constValue && isa(*constValue)) { - ConstantInt *idxPtr = cast(gep->getOperand(2)); - uint64_t memberIdx = *(idxPtr->getValue().getRawData()); - - StructType *STy = cast(structType); - if (!STy->isLiteral()) { - string strName(structType->getStructName().data()); - map::iterator it = Structs.find(strName); - if (it != Structs.end()) { - Value *ret = findStructMemberName(it->second, memberIdx, builder); - if (ret) - return ret; - } - } - } - } - - // we've found an array - if (PTy->getPointerElementType()->getTypeID() == Type::ArrayTyID && isa(*ptrOperand)) { - return determineVariableName_dynamic((Instruction *)ptrOperand); - } - return determineVariableName_dynamic((Instruction *)gep); - } - return getOrInsertVarName_dynamic(string(operand->getName().data()), builder); - } - - if (isa(*operand) || isa(*operand)) { - return determineVariableName_dynamic((Instruction *)(operand)); - } - if (isa(I)) { - return getOrInsertVarName_dynamic(I->getName().str(), builder); - } - // if we cannot determine the name, then return * - return getOrInsertVarName_dynamic("*", builder); -} - -void DiscoPoP::getTrueVarNamesFromMetadata(Region *TopRegion, Node *root, - std::map *trueVarNamesFromMetadataMap) { - int lid = 0; - for (Region::block_iterator bb = TopRegion->block_begin(); bb != TopRegion->block_end(); ++bb) { - for (BasicBlock::iterator instruction = (*bb)->begin(); instruction != (*bb)->end(); ++instruction) { - // search for call instructions to @llvm.dbg.declare - if (isa(instruction)) { - Function *f = (cast(instruction))->getCalledFunction(); - if (f) { - StringRef funcName = f->getName(); - if (funcName.find("llvm.dbg.declare") != string::npos) // llvm debug calls - { - CallInst *call = cast(instruction); - // check if @llvm.dbg.declare is called - // int cmp_res = - // dbg_declare.compare(call->getCalledFunction()->getName().str()); - // if(cmp_res == 0){ - // call to @llvm.dbg.declare found - // extract original and working variable name - string SRCVarName; - string IRVarName; - - Metadata *Meta = cast(call->getOperand(0))->getMetadata(); - if (isa(Meta)) { - Value *V = cast(Meta)->getValue(); - IRVarName = V->getName().str(); - } - DIVariable *V = cast(cast(call->getOperand(1))->getMetadata()); - SRCVarName = V->getName().str(); - - // add to trueVarNamesFromMetadataMap - // overwrite entry if already existing - if (trueVarNamesFromMetadataMap->find(IRVarName) == trueVarNamesFromMetadataMap->end()) { - // not found - trueVarNamesFromMetadataMap->insert(std::pair(IRVarName, SRCVarName)); - } else { - // found - (*trueVarNamesFromMetadataMap)[IRVarName] = SRCVarName; - } - } - } - } - } - } -} - -void DiscoPoP::processStructTypes(string const &fullStructName, MDNode *structNode) { - assert(structNode && "structNode cannot be NULL"); - DIType *strDes = cast(structNode); - assert(strDes->getTag() == dwarf::DW_TAG_structure_type); - // sometimes it's impossible to get the list of struct members (e.g badref) - if (structNode->getNumOperands() <= 10 || structNode->getOperand(10) == NULL) { - errs() << "cannot process member list of this struct: \n"; - structNode->dump(); - return; - } - Structs[fullStructName] = structNode; - - MDNode *memberListNodes = cast(structNode->getOperand(10)); - for (unsigned i = 0; i < memberListNodes->getNumOperands(); ++i) { - assert(memberListNodes->getOperand(i)); - MDNode *member = cast(memberListNodes->getOperand(i)); - DINode *memberDes = cast(member); - // DIDescriptor memberDes(member); - if (memberDes->getTag() == dwarf::DW_TAG_member) { - assert(member->getOperand(9)); - MDNode *memberType = cast(member->getOperand(9)); - DIType *memberTypeDes = cast(memberType); - // DIType memberTypeDes(memberType); - if (memberTypeDes->getTag() == dwarf::DW_TAG_structure_type) { - string fullName = ""; - // try to get namespace - if (memberType->getNumOperands() > 2 && structNode->getOperand(2) != NULL) { - MDNode *namespaceNode = cast(structNode->getOperand(2)); - DINamespace *dins = cast(namespaceNode); - // DINameSpace dins(namespaceNode); - fullName = "struct." + string(dins->getName().data()) + "::"; - } - // fullName += string(memberType->getOperand(3)->getName().data()); - fullName += (dyn_cast(memberType->getOperand(3)))->getString(); - - if (Structs.find(fullName) == Structs.end()) - processStructTypes(fullName, memberType); - } - } - } -} - -/********** Output functions *********/ -string DiscoPoP::xmlEscape(string data) { - string::size_type pos = 0; - for (;;) { - pos = data.find_first_of("\"&<>", pos); - if (pos == string::npos) - break; - string replacement; - switch (data[pos]) { - case '\"': - replacement = """; - break; - case '&': - replacement = "&"; - break; - case '<': - replacement = "<"; - break; - case '>': - replacement = ">"; - break; - default:; - } - data.replace(pos, 1, replacement); - pos += replacement.size(); - }; - return data; -} - -void DiscoPoP::secureStream() { - outOriginalVariables = new std::ofstream(); - std::string tmp(getenv("DOT_DISCOPOP_PROFILER")); - tmp += "/OriginalVariables.txt"; - outOriginalVariables->open(tmp.data(), std::ios_base::app); - - outCUs = new std::ofstream(); - std::string tmp2(getenv("DOT_DISCOPOP_PROFILER")); - tmp2 += "/Data.xml"; - outCUs->open(tmp2.data(), std::ios_base::app); -} - -string DiscoPoP::getLineNumbersString(set LineNumbers) { - string line = ""; - for (auto li : LineNumbers) { - std::string temp = ',' + dputil::decodeLID(li); - if (temp != ",*") { - if (line == "") { - line = dputil::decodeLID(li); - } else { - line = line + temp; - } - } - } - return line; -} - -string DiscoPoP::getChildrenNodesString(Node *root) { - string childrenIDs = ""; - int i = 0; - std::for_each(root->childrenNodes.begin(), root->childrenNodes.end(), [&](Node *node) { - if (i == 0) { - childrenIDs = node->ID; - i++; - } else { - childrenIDs += "," + node->ID; - } - }); - return childrenIDs; -} - -void DiscoPoP::printData(Node *root) { - *outCUs << "" << endl << endl; - - printTree(root, true); - - *outCUs << "" << endl << endl << endl; - - closeOutputFiles(); -} - -void DiscoPoP::printTree(Node *root, bool isRoot) { - printNode(root, isRoot); - - std::for_each(root->childrenNodes.begin(), root->childrenNodes.end(), [&](Node *node) { - if (node->type == nodeTypes::func) { - isRoot = false; - } - printTree(node, isRoot); - }); -} - -void DiscoPoP::printNode(Node *root, bool isRoot) { - if (root->name.find("llvm")) { - string start = ""; - if (root->type == nodeTypes::loop) { - start = loopStartLines[root->ID]; - } else { - start = dputil::decodeLID(root->startLine); - } - *outCUs << "\tID) << "\"" - << " type=\"" << root->type << "\"" - << " name=\"" << xmlEscape(root->name) << "\"" - << " startsAtLine = \"" << start << "\"" - << " endsAtLine = \"" << dputil::decodeLID(root->endLine) << "\"" - << ">" << endl; - *outCUs << "\t\t" << getChildrenNodesString(root) << "" << endl; - if (root->type == nodeTypes::func || root->type == nodeTypes::dummy) { - *outCUs << "\t\t" << endl; - for (auto ai : root->argumentsList) { - *outCUs << "\t\t\t" - << xmlEscape(ai.name) << "" << endl; - } - *outCUs << "\t\t" << endl; - - string rlVals = ""; - for (auto rl : root->returnLines) { - rlVals += dputil::decodeLID(rl) + ", "; - } - *outCUs << "\t\t" << rlVals << "" << endl; - } - - if (root->type == nodeTypes::cu) { - CU *cu = static_cast(root); - *outCUs << "\t\t" << cu->BBID << "" << endl; - *outCUs << "\t\t" << cu->readDataSize << "" << endl; - *outCUs << "\t\t" << cu->writeDataSize << "" << endl; - *outCUs << "\t\t" << cu->performsFileIO << "" << endl; - - *outCUs << "\t\t" << cu->instructionsCount << "" << endl; - *outCUs << "\t\tinstructionsLineNumbers).size() << "\">" - << getLineNumbersString(cu->instructionsLineNumbers) << "" << endl; - *outCUs << "\t\treadPhaseLineNumbers).size() << "\">" - << getLineNumbersString(cu->readPhaseLineNumbers) << "" << endl; - *outCUs << "\t\twritePhaseLineNumbers).size() << "\">" - << getLineNumbersString(cu->writePhaseLineNumbers) << "" << endl; - *outCUs << "\t\treturnInstructions).size() << "\">" - << getLineNumbersString(cu->returnInstructions) << "" << endl; - *outCUs << "\t\t" << endl; - for (auto sucCUi : cu->successorCUs) { - *outCUs << "\t\t\t" << sucCUi << "" << endl; - } - *outCUs << "\t\t" << endl; - - *outCUs << "\t\t" << endl; - for (auto lvi : cu->localVariableNames) { - *outCUs << "\t\t\t" - << xmlEscape(lvi.name) << "" << endl; - } - *outCUs << "\t\t" << endl; - - *outCUs << "\t\t" << endl; - for (auto gvi : cu->globalVariableNames) { - *outCUs << "\t\t\t" - << xmlEscape(gvi.name) << "" << endl; - } - *outCUs << "\t\t" << endl; - - *outCUs << "\t\t" << endl; - for (auto i : (cu->callLineTofunctionMap)) { - for (auto ii : i.second) { - *outCUs << "\t\t\t" << ii->ID << "" - << endl; - // specifica for recursive fucntions inside loops. (Mo 5.11.2019) - *outCUs << "\t\t\t\t" << ii->recursiveFunctionCall << "" - << endl; - } - } - *outCUs << "\t\t" << endl; - } - - *outCUs << "\t" << endl << endl; - } -} - -void DiscoPoP::closeOutputFiles() { - - if (outCUs != NULL && outCUs->is_open()) { - outCUs->flush(); - outCUs->close(); - } - - if (outOriginalVariables != NULL && outOriginalVariables->is_open()) { - outOriginalVariables->flush(); - outOriginalVariables->close(); - } - - // delete outCUs; -} -/************** End of output functions *******************/ - -/* metadata format in LLVM IR: -!5 = metadata !{ - i32, ;; Tag (see below) // DW_TAG_pointer_type: 0 - metadata, ;; Reference to context // 1 - metadata, ;; Name (may be "" for anonymous types) // 2 - metadata, ;; Reference to file where defined (may be NULL) // 3 - i32, ;; Line number where defined (may be 0) // 4 - i64, ;; Size in bits // 5 - i64, ;; Alignment in bits // 6 - i64, ;; Offset in bits // 7 - i32, ;; Flags to encode attributes, e.g. private // 8 - metadata, ;; Reference to type derived from // 9 --> get operand at -index 9 metadata, ;; (optional) Name of the Objective C property associated with - ;; Objective-C an ivar, or the type of which this - ;; pointer-to-member is pointing to members of. - metadata, ;; (optional) Name of the Objective C property getter selector. - metadata, ;; (optional) Name of the Objective C property setter selector. - i32 ;; (optional) Objective C property attributes. -} - -A real case would be: -!2 = metadata !{ - i32 524307, ;; Tag // 0 - metadata !1, ;; Context // 1 - metadata !"Color", ;; Name // 2 - metadata !1, ;; Compile unit // 3 - i32 1, ;; Line number // 4 - i64 96, ;; Size in bits // 5 - i64 32, ;; Align in bits // 6 - i64 0, ;; Offset in bits // 7 - i32 0, ;; Flags // 8 - null, ;; Derived From // 9 - metadata !3, ;; Elements // 10 --> list of elements - i32 0 ;; Runtime Language -} -*/ -// TODO: atomic variables -void DiscoPoP::runOnBasicBlock(BasicBlock &BB) { - for (BasicBlock::iterator BI = BB.begin(), E = BB.end(); BI != E; ++BI) { - if (DbgDeclareInst *DI = dyn_cast(BI)) { - assert(DI->getOperand(0)); - if (AllocaInst *alloc = dyn_cast(DI->getOperand(0))) { - Type *type = alloc->getAllocatedType(); - Type *structType = type; - unsigned depth = 0; - if (type->getTypeID() == Type::PointerTyID) { - while (structType->getTypeID() == Type::PointerTyID) { - structType = cast(structType)->getElementType(); - ++depth; - } - } - if (structType->getTypeID() == Type::StructTyID) { - assert(DI->getOperand(1)); - MDNode *varDesNode = DI->getVariable(); - assert(varDesNode->getOperand(5)); - MDNode *typeDesNode = cast(varDesNode->getOperand(5)); - MDNode *structNode = typeDesNode; - if (type->getTypeID() == Type::PointerTyID) { - MDNode *ptr = typeDesNode; - for (unsigned i = 0; i < depth; ++i) { - assert(ptr->getOperand(9)); - ptr = cast(ptr->getOperand(9)); - } - structNode = ptr; - } - DINode *strDes = cast(structNode); - // DIDescriptor strDes(structNode); - // handle the case when we have pointer to struct (or pointer to - // pointer to struct ...) - if (strDes->getTag() == dwarf::DW_TAG_pointer_type) { - DINode *ptrDes = strDes; - do { - if (structNode->getNumOperands() < 10) - break; - assert(structNode->getOperand(9)); - structNode = cast(structNode->getOperand(9)); - ptrDes = cast(structNode); - } while (ptrDes->getTag() != dwarf::DW_TAG_structure_type); - } - - if (strDes->getTag() == dwarf::DW_TAG_typedef) { - assert(strDes->getOperand(9)); - structNode = cast(strDes->getOperand(9)); - } - strDes = cast(structNode); - if (strDes->getTag() == dwarf::DW_TAG_structure_type) { - string strName(structType->getStructName().data()); - if (Structs.find(strName) == Structs.end()) { - processStructTypes(strName, structNode); - } - } - } - } - } - // alloca instruction - else if (isa(BI)) { - AllocaInst *AI = cast(BI); - - // if the option is set, check if the AllocaInst is static at the entry - // block of a function and skip it's instrumentation. This leads to a - // strong improvement of the profiling time if a lot of function calls are - // used, but results in a worse accurracy. As the default, the accurate - // profiling is used. Effectively, this check disables the instrumentation - // of allocas which belong to function parameters. - - if (DP_MEMORY_PROFILING_SKIP_FUNCTION_ARGUMENTS) { - if (!AI->isStaticAlloca()) { - // only instrument non-static alloca instructions - instrumentAlloca(AI); - } - } else { - // instrument every alloca instruction - instrumentAlloca(AI); - } - - } - // load instruction - else if (isa(BI)) { - instrumentLoad(cast(BI)); - } - // // store instruction - else if (isa(BI)) { - instrumentStore(cast(BI)); - } - // call and invoke - else if (isaCallOrInvoke(&*BI)) { - Function *F; - if (isa(BI)) - F = (cast(BI))->getCalledFunction(); - else if (isa(BI)) - F = (cast(BI))->getCalledFunction(); - - // For ordinary function calls, F has a name. - // However, sometimes the function being called - // in IR is encapsulated by "bitcast()" due to - // the way of compiling and linking. In this way, - // getCalledFunction() method returns NULL. - StringRef fn = ""; - if (F) { - fn = F->getName(); - if (fn.find("__dp_") != string::npos) // avoid instrumentation calls - { - continue; - } - if (fn.find("__clang_") != string::npos) // clang helper calls - { - continue; - } - if (fn.equals("pthread_exit")) { - // pthread_exit does not return to its caller. - // Therefore, we insert DpFuncExit before pthread_exit - IRBuilder<> IRBRet(&*BI); - ArrayRef arguments({ConstantInt::get(Int32, getLID(&*BI, fileID)), ConstantInt::get(Int32, 0)}); - IRBRet.CreateCall(DpFuncExit, arguments); - continue; - } - if (fn.equals("exit") || F->doesNotReturn()) // using exit() to terminate program - { - // only insert DpFinalize right before the main program exits - insertDpFinalize(&*BI); - continue; - } - if (fn.equals("_Znam") || fn.equals("_Znwm") || fn.equals("malloc")) { - if (isa(BI)) { - instrumentNewOrMalloc(cast(BI)); - } else if (isa(BI)) { - instrumentNewOrMalloc(cast(BI)); - } - continue; - } - if (fn.equals("realloc")) { - if (isa(BI)) { - instrumentRealloc(cast(BI)); - } else if (isa(BI)) { - instrumentRealloc(cast(BI)); - } - continue; - } - if (fn.equals("calloc")) { - if (isa(BI)) { - instrumentCalloc(cast(BI)); - } else if (isa(BI)) { - instrumentCalloc(cast(BI)); - } - } - - if (fn.equals("posix_memalign")) { - if (isa(BI)) { - instrumentPosixMemalign(cast(BI)); - } else if (isa(BI)) { - instrumentPosixMemalign(cast(BI)); - } - continue; - } - if (fn.equals("_ZdlPv") || fn.equals("free")) { - instrumentDeleteOrFree(cast(BI)); - continue; - } - } - LID lid = getLID(&*BI, fileID); - if (lid > 0) // calls on non-user code are not instrumented - { - IRBuilder<> IRBCall(&*BI); - IRBCall.CreateCall(DpCallOrInvoke, ConstantInt::get(Int32, lid)); - if (DP_DEBUG) { - if (isa(BI)) { - if (!fn.equals("")) - errs() << "calling " << fn << " on " << lid << "\n"; - else - errs() << "calling unknown function on " << lid << "\n"; - } else { - if (!fn.equals("")) - errs() << "invoking " << fn << " on " << lid << "\n"; - else - errs() << "invoking unknown function on " << lid << "\n"; - } - } - } - } - // return - else if (isa(BI)) { - LID lid = getLID(&*BI, fileID); - assert((lid > 0) && "Returning on LID = 0!"); - - Function *parent = BB.getParent(); - assert(parent != NULL); - StringRef fn = parent->getName(); - - if (fn.equals("main")) // returning from main - { - insertDpFinalize(&*BI); - } else { - IRBuilder<> IRBRet(&*BI); - ArrayRef arguments({ConstantInt::get(Int32, lid), ConstantInt::get(Int32, 0)}); - IRBRet.CreateCall(DpFuncExit, arguments); - } - - if (DP_DEBUG) { - errs() << fn << " returning on " << lid << "\n"; - } - } - } -} - -// Instrumentation function inserters. -void DiscoPoP::instrumentAlloca(AllocaInst *toInstrument) { - LID lid = getLID(toInstrument, fileID); - if (lid == 0) - return; - - // NOTE: manual memory management using malloc etc. not covered yet! - - IRBuilder<> IRB(toInstrument->getNextNode()); - - vector args; - args.push_back(ConstantInt::get(Int32, lid)); - args.push_back(determineVariableName_dynamic(toInstrument)); - - bool isGlobal; - // Value *startAddr = PtrToIntInst::CreatePointerCast(toInstrument, Int64, "", - // toInstrument->getNextNonDebugInstruction()); - Value *startAddr = IRB.CreatePtrToInt(toInstrument, Int64, ""); - args.push_back(startAddr); - - Value *endAddr = startAddr; - uint64_t elementSizeInBytes = toInstrument->getAllocatedType()->getScalarSizeInBits() / 8; - Value *numElements = toInstrument->getOperand(0); - if (toInstrument->isArrayAllocation()) { - // endAddr = startAddr + allocated size - endAddr = IRB.CreateAdd(startAddr, IRB.CreateIntCast(numElements, Int64, true)); - } else if (toInstrument->getAllocatedType()->isArrayTy()) { - // unpack potentially multidimensional allocations - - Type *typeToParse = toInstrument->getAllocatedType(); - Type *elementType; - - uint64_t tmp_numElements = 1; - - // unpack multidimensional allocations - while (typeToParse->isArrayTy()) { - // extract size from current dimension and multiply to numElements - tmp_numElements *= cast(typeToParse)->getNumElements(); - // proceed one dimension - typeToParse = typeToParse->getArrayElementType(); - } - // typeToParse now contains the element type - elementType = typeToParse; - - // allocated size = Element size in Bytes * Number of elements - elementSizeInBytes = elementType->getScalarSizeInBits() / 8; - - // endAddr = startAddr + allocated size - numElements = ConstantInt::get(Int64, tmp_numElements); - endAddr = IRB.CreateAdd(startAddr, IRB.CreateIntCast(numElements, Int64, true)); - } - - args.push_back(endAddr); - args.push_back( - IRB.CreateMul(IRB.CreateIntCast(numElements, Int64, true), ConstantInt::get(Int64, elementSizeInBytes))); - args.push_back(IRB.CreateIntCast(numElements, Int64, true)); - IRB.CreateCall(DpAlloca, args, ""); -} - -void DiscoPoP::instrumentNewOrMalloc(CallBase *toInstrument) { - // add instrumentation for new instructions or calls to malloc - LID lid = getLID(toInstrument, fileID); - if (lid == 0) - return; - - // Determine correct placement for the call to __dp_new - Instruction *nextInst; - if (isa(toInstrument)) { - nextInst = toInstrument->getNextNonDebugInstruction(); - } else if (isa(toInstrument)) { - // Invoke instructions are always located at the end of a basic block. - // Invoke instructions may throw errors, in which case the successor is a - // "landing pad" basic block. If no error is thrown, the control flow is - // resumed at a "normal destination" basic block. Set the first instruction - // of the normal destination as nextInst in order to add the Instrumentation - // at the correct location. - nextInst = cast(toInstrument)->getNormalDest()->getFirstNonPHIOrDbg(); - } - - IRBuilder<> IRB(nextInst); - - vector args; - args.push_back(ConstantInt::get(Int32, lid)); - - Value *startAddr = PtrToIntInst::CreatePointerCast(toInstrument, Int64, "", nextInst); - Value *endAddr = startAddr; - Value *numBytes = toInstrument->getArgOperand(0); - - args.push_back(startAddr); - args.push_back(endAddr); // currently unused - args.push_back(numBytes); - - IRB.CreateCall(DpNew, args, ""); -} - -void DiscoPoP::instrumentRealloc(CallBase *toInstrument) { - // add instrumentation for calls to realloc - LID lid = getLID(toInstrument, fileID); - if (lid == 0) - return; - - // Determine correct placement for the call to __dp_new - Instruction *nextInst; - if (isa(toInstrument)) { - nextInst = toInstrument->getNextNonDebugInstruction(); - } else if (isa(toInstrument)) { - // Invoke instructions are always located at the end of a basic block. - // Invoke instructions may throw errors, in which case the successor is a - // "landing pad" basic block. If no error is thrown, the control flow is - // resumed at a "normal destination" basic block. Set the first instruction - // of the normal destination as nextInst in order to add the Instrumentation - // at the correct location. - nextInst = cast(toInstrument)->getNormalDest()->getFirstNonPHIOrDbg(); - } - - IRBuilder<> IRB(nextInst); - vector args; - - // deallocate - args.push_back(ConstantInt::get(Int32, lid)); - Value *startAddr = - PtrToIntInst::CreatePointerCast(toInstrument->getArgOperand(0), Int64, "", toInstrument->getNextNode()); - args.push_back(startAddr); - IRB.CreateCall(DpDelete, args, ""); - args.clear(); - - // allocate - args.push_back(ConstantInt::get(Int32, lid)); - Value *endAddr = startAddr; - Value *numBytes = toInstrument->getArgOperand(1); - args.push_back(startAddr); - args.push_back(endAddr); // currently unused - args.push_back(numBytes); - - IRB.CreateCall(DpNew, args, ""); -} - -void DiscoPoP::instrumentCalloc(CallBase *toInstrument) { - // add instrumentation for calls to calloc - LID lid = getLID(toInstrument, fileID); - if (lid == 0) - return; - - // Determine correct placement for the call to __dp_new - Instruction *nextInst; - if (isa(toInstrument)) { - nextInst = toInstrument->getNextNonDebugInstruction(); - } else if (isa(toInstrument)) { - // Invoke instructions are always located at the end of a basic block. - // Invoke instructions may throw errors, in which case the successor is a - // "landing pad" basic block. If no error is thrown, the control flow is - // resumed at a "normal destination" basic block. Set the first instruction - // of the normal destination as nextInst in order to add the Instrumentation - // at the correct location. - nextInst = cast(toInstrument)->getNormalDest()->getFirstNonPHIOrDbg(); - } - - IRBuilder<> IRB(nextInst); - - vector args; - args.push_back(ConstantInt::get(Int32, lid)); - - Value *startAddr = PtrToIntInst::CreatePointerCast(toInstrument, Int64, "", nextInst); - Value *endAddr = startAddr; - Value *numBytes = IRB.CreateMul(toInstrument->getArgOperand(0), toInstrument->getArgOperand(1)); - - args.push_back(startAddr); - args.push_back(endAddr); // currently unused - args.push_back(numBytes); - - IRB.CreateCall(DpNew, args, ""); -} - -void DiscoPoP::instrumentPosixMemalign(CallBase *toInstrument) { - // add instrumentation for calls to posix_memalign - LID lid = getLID(toInstrument, fileID); - if (lid == 0) - return; - - // Determine correct placement for the call to __dp_new - Instruction *nextInst; - if (isa(toInstrument)) { - nextInst = toInstrument->getNextNonDebugInstruction(); - } else if (isa(toInstrument)) { - // Invoke instructions are always located at the end of a basic block. - // Invoke instructions may throw errors, in which case the successor is a - // "landing pad" basic block. If no error is thrown, the control flow is - // resumed at a "normal destination" basic block. Set the first instruction - // of the normal destination as nextInst in order to add the Instrumentation - // at the correct location. - nextInst = cast(toInstrument)->getNormalDest()->getFirstNonPHIOrDbg(); - } - - IRBuilder<> IRB(nextInst); - - vector args; - args.push_back(ConstantInt::get(Int32, lid)); - - Value *startAddr = PtrToIntInst::CreatePointerCast(toInstrument->getArgOperand(0), Int64, "", nextInst); - Value *endAddr = startAddr; - Value *numBytes = toInstrument->getArgOperand(2); - - args.push_back(startAddr); - args.push_back(endAddr); // currently unused - args.push_back(numBytes); - - IRB.CreateCall(DpNew, args, ""); -} - -void DiscoPoP::instrumentDeleteOrFree(CallBase *toInstrument) { - // add instrumentation for delete instructions or calls to free - LID lid = getLID(toInstrument, fileID); - if (lid == 0) - return; - IRBuilder<> IRB(toInstrument->getNextNonDebugInstruction()); - - vector args; - args.push_back(ConstantInt::get(Int32, lid)); - - Value *startAddr = - PtrToIntInst::CreatePointerCast(toInstrument->getArgOperand(0), Int64, "", toInstrument->getNextNode()); - - args.push_back(startAddr); - - IRB.CreateCall(DpDelete, args, ""); -} - -void DiscoPoP::instrumentLoad(LoadInst *toInstrument) { - - LID lid = getLID(toInstrument, fileID); - if (lid == 0) - return; - - vector args; - - args.push_back(ConstantInt::get(Int32, lid)); - - Value *memAddr = PtrToIntInst::CreatePointerCast(toInstrument->getPointerOperand(), Int64, "", toInstrument); - args.push_back(memAddr); - - args.push_back(determineVariableName_dynamic(toInstrument)); - -#ifdef SKIP_DUP_INSTR - Twine name = Twine("L").concat(Twine(uniqueNum)); - - GlobalVariable *addrTracker = new GlobalVariable(*this->ThisModule, - Int64, // trackerType - false, GlobalVariable::PrivateLinkage, - Constant::getNullValue(Int64), // trackerType - name); - GlobalVariable *countTracker = new GlobalVariable(*this->ThisModule, Int64, false, GlobalVariable::PrivateLinkage, - Constant::getNullValue(Int64), name.concat(Twine("count"))); - uniqueNum++; - - // Load current values before instr - LoadInst *currentAddrTracker = new LoadInst::LoadInst(addrTracker, Twine(), toInstrument); - LoadInst *currentCount = new LoadInst::LoadInst(countTracker, Twine(), toInstrument); - - // add instr before before - args.push_back(currentAddrTracker); - args.push_back(currentCount); -#endif - CallInst::Create(DpRead, args, "", toInstrument); - -#ifdef SKIP_DUP_INSTR - // Post instrumentation call - // Create updates - StoreInst *addrUpdate = new StoreInst::StoreInst(memAddr, addrTracker); - BinaryOperator::BinaryOperator *incCount = - BinaryOperator::Create(Instruction::Add, currentCount, ConstantInt::get(Int64, 1)); - StoreInst *countUpdate = new StoreInst::StoreInst(incCount, countTracker); - - // add updates after before - addrUpdate->insertAfter(toInstrument); - incCount->insertAfter(toInstrument); - countUpdate->insertAfter(incCount); -#endif -} - -void DiscoPoP::instrumentStore(StoreInst *toInstrument) { - - LID lid = getLID(toInstrument, fileID); - if (lid == 0) - return; - - vector args; - args.push_back(ConstantInt::get(Int32, lid)); - - Value *memAddr = PtrToIntInst::CreatePointerCast(toInstrument->getPointerOperand(), Int64, "", toInstrument); - args.push_back(memAddr); - - args.push_back(determineVariableName_dynamic(toInstrument)); - -#ifdef SKIP_DUP_INSTR - Twine name = Twine("S").concat(Twine(uniqueNum)); - - GlobalVariable *addrTracker = new GlobalVariable(*this->ThisModule, - Int64, // trackerType - false, GlobalVariable::PrivateLinkage, - Constant::getNullValue(Int64), // trackerType - name); - GlobalVariable *countTracker = new GlobalVariable(*this->ThisModule, Int64, false, GlobalVariable::PrivateLinkage, - Constant::getNullValue(Int64), name.concat(Twine("count"))); - uniqueNum++; - - // Load current values before instr - LoadInst *currentAddrTracker = new LoadInst::LoadInst(addrTracker, Twine(), toInstrument); - LoadInst *currentCount = new LoadInst::LoadInst(countTracker, Twine(), toInstrument); - - // add instr before before - args.push_back(currentAddrTracker); - args.push_back(currentCount); -#endif - - CallInst::Create(DpWrite, args, "", toInstrument); - -#ifdef SKIP_DUP_INSTR - // Post instrumentation call - // Create updates - StoreInst *addrUpdate = new StoreInst::StoreInst(memAddr, addrTracker); - BinaryOperator::BinaryOperator *incCount = - BinaryOperator::Create(Instruction::Add, currentCount, ConstantInt::get(Int64, 1)); - StoreInst *countUpdate = new StoreInst::StoreInst(incCount, countTracker); - - // add updates after before - addrUpdate->insertAfter(toInstrument); - incCount->insertAfter(toInstrument); - countUpdate->insertAfter(incCount); -#endif -} - -void DiscoPoP::insertDpFinalize(Instruction *before) { - LID lid = getLID(before, fileID); - assert((lid > 0) && "Returning on an invalid LID."); - IRBuilder<> IRB(before); - IRB.CreateCall(DpFinalize, ConstantInt::get(Int32, lid)); -} - -void DiscoPoP::instrumentFuncEntry(Function &F) { - BasicBlock &entryBB = F.getEntryBlock(); - LID lid = 0; - int32_t isStart = 0; - - StringRef fn = F.getName(); - if (fn.equals("main")) { - isStart = 1; - - // insert 'allocations' of global variables - Instruction *insertBefore = &*entryBB.begin(); - - auto tmp_end = F.getParent()->getGlobalList().end(); - tmp_end--; // necessary, since the list of Globals is modified when e.g. new - // strings are created. - for (auto Global_it = F.getParent()->getGlobalList().begin(); Global_it != tmp_end; Global_it++) { - // ignore globals which make use of "Appending Linkage", since they are - // system internal and do not behave like regular values. An example for - // such a value is @llvm.global_ctors - if (cast(&*Global_it)->hasAppendingLinkage()) { - continue; - } - - IRBuilder<> IRB(insertBefore->getNextNode()); - - vector args; - args.push_back(ConstantInt::get(Int32, lid)); - args.push_back(getOrInsertVarName_dynamic(Global_it->getName().str(), IRB)); - - bool isGlobal; - // Value *startAddr = PtrToIntInst::CreatePointerCast(toInstrument, Int64, - // "", toInstrument->getNextNonDebugInstruction()); - Value *startAddr = IRB.CreatePtrToInt(cast(&*Global_it), Int64, ""); - args.push_back(startAddr); - - Value *endAddr = startAddr; - uint64_t numElements = 1; - uint64_t allocatedSize = Global_it->getValueType()->getScalarSizeInBits(); - if (Global_it->getValueType()->isArrayTy()) { - // unpack potentially multidimensional allocations - Type *typeToParse = Global_it->getValueType(); - Type *elementType; - - // unpack multidimensional allocations - while (typeToParse->isArrayTy()) { - // extract size from current dimension and multiply to numElements - numElements *= cast(typeToParse)->getNumElements(); - // proceed one dimension - typeToParse = typeToParse->getArrayElementType(); - } - // typeToParse now contains the element type - elementType = typeToParse; - - // allocated size = Element size in Bytes * Number of elements - auto elementSizeInBytes = elementType->getScalarSizeInBits() / 8; - allocatedSize = elementSizeInBytes * numElements; - - // endAddr = startAddr + allocated size - endAddr = IRB.CreateAdd(startAddr, ConstantInt::get(Int64, allocatedSize)); - } - - args.push_back(endAddr); - args.push_back(ConstantInt::get(Int64, allocatedSize)); - args.push_back(ConstantInt::get(Int64, numElements)); - // REMOVED TO FIX INCORRECT STACK ADDRESS TRACKING - // TODO: maybe replace with explicit registration of global variables - // IRB.CreateCall(DpAlloca, args, ""); - } - } - - // We always want to insert __dp_func_entry at the beginning - // of the basic block, but we need the first valid LID to - // get the entry line of the function. - for (BasicBlock::iterator BI = entryBB.begin(), EI = entryBB.end(); BI != EI; ++BI) { - lid = getLID(&*BI, fileID); - if (lid > 0 && !isa(BI)) { - IRBuilder<> IRB(&*entryBB.begin()); - // NOTE: Changed to arrayref - ArrayRef arguments({ConstantInt::get(Int32, lid), ConstantInt::get(Int32, isStart)}); - IRB.CreateCall(DpFuncEntry, arguments); - if (DP_DEBUG) { - errs() << "DiscoPoP: funcEntry instrumented\n"; - } - break; - } - } - assert((lid > 0) && "Function entry is not instrumented because LID are all " - "invalid for the entry block."); -} - -void DiscoPoP::instrumentLoopEntry(BasicBlock *bb, int32_t id) { - BasicBlock *currentBB = bb; - vector args; - LID lid = 0; - - // Take care of the order of instrumentation functions for loop entry - // and exit. Loop exit must appear before the next loop entry. - // Usually every loop has a .end block as the exit block, thus the - // exit of a loop will not be the entry of another loop. The first if - // check is just in case the blocks are organized in a abnormal way. - for (BasicBlock::iterator BI = currentBB->begin(), EI = currentBB->end(); BI != EI; ++BI) { - if (isa(BI)) { - Function *tmpF = (cast(BI))->getCalledFunction(); - StringRef tmpFn = tmpF->getName(); - if (tmpFn.find("__dp_loop_exit") != string::npos) - continue; - } - lid = getLID(&*BI, fileID); - if (lid > 0 && !isa(BI)) { - args.push_back(ConstantInt::get(Int32, lid)); - args.push_back(ConstantInt::get(Int32, id)); - CallInst::Create(DpLoopEntry, args, "", &*BI); - break; - } - } - // assert((lid > 0) && "Loop entry is not instrumented because LID are all - // invalid for the whole basic block."); -} - -void DiscoPoP::instrumentLoopExit(BasicBlock *bb, int32_t id) { - BasicBlock *currentBB = bb; - vector args; - LID lid = 0; - - for (BasicBlock::iterator BI = currentBB->begin(), EI = currentBB->end(); BI != EI; ++BI) { - lid = getLID(&*BI, fileID); - if (lid > 0 && !isa(BI)) { - args.push_back(ConstantInt::get(Int32, lid)); - args.push_back(ConstantInt::get(Int32, id)); - CallInst::Create(DpLoopExit, args, "", - &*currentBB->begin()); // always insert to the beiginning - break; - } - } } diff --git a/DiscoPoP/DiscoPoP.hpp b/DiscoPoP/DiscoPoP.hpp index 3a39339a0..44c32d111 100644 --- a/DiscoPoP/DiscoPoP.hpp +++ b/DiscoPoP/DiscoPoP.hpp @@ -48,7 +48,9 @@ #include "llvm/Transforms/Instrumentation.h" #include "DPUtils.hpp" -#include "InstructionDG.hpp" +#include "hybrid_analysis/InstructionDG.hpp" + +#include "Structs.hpp" #include #include @@ -64,144 +66,31 @@ #include +#include "Globals.hpp" + #define DP_DEBUG false +#define ClCheckLoopPar true +#define DumpToDot false +#define DP_BRANCH_TRACKING \ + true // toggles the creation of instrumentation calls for tracking taken + // branches. Required by the graph pruning step of the DiscoPoP + // optimizer. +#define DP_DEBUG false +#define DP_VERBOSE false // prints warning messages +#define DP_hybrid_DEBUG false + using namespace llvm; using namespace std; using namespace dputil; +/* // Command line options static cl::opt ClCheckLoopPar("dp-loop-par", cl::init(true), cl::desc("Check loop parallelism"), cl::Hidden); static cl::opt DumpToDot("dp-omissions-dump-dot", cl::init(false), cl::desc("Generate a .dot representation of the CFG and DG"), cl::Hidden); - -namespace { - -STATISTIC(totalInstrumentations, "Total DP-Instrumentations"); -STATISTIC(removedInstrumentations, "Disregarded DP-Instructions"); - -// CUGeneration - -static unsigned int CUIDCounter; -static unsigned int bbDepCount; -static bool defaultIsGlobalVariableValue; -int32_t fileID; - -typedef struct Variable_struct { - string name; - string type; - string defLine; - string isArray; - bool readAccess; - bool writeAccess; - string sizeInBytes; - - Variable_struct(const Variable_struct &other) - : name(other.name), type(other.type), defLine(other.defLine), readAccess(other.readAccess), - writeAccess(other.writeAccess), sizeInBytes(other.sizeInBytes) {} - - Variable_struct(string n, string t, string d, bool readAccess, bool writeAccess, string sizeInBytes) - : name(n), type(t), defLine(d), readAccess(readAccess), writeAccess(writeAccess), sizeInBytes(sizeInBytes) {} - - // We have a set of this struct. The set doesn't know how to order the - // elements. - inline bool operator<(const Variable_struct &rhs) const { return name < rhs.name; } - - inline bool operator>(const Variable_struct &rhs) const { return name > rhs.name; } - -} Variable; - -enum nodeTypes { cu, func, loop, dummy } type; - -typedef struct Node_struct { - string ID; - nodeTypes type; - int startLine; - int endLine; - BasicBlock *BB; - - // Only for func type - string name; - vector argumentsList; - set returnLines; - - vector childrenNodes; - Node_struct *parentNode; - - // isRecursive function (Mo 5.11.2019) - string recursiveFunctionCall = ""; - - Node_struct() { - ID = to_string(fileID) + ":" + to_string(CUIDCounter++); - parentNode = NULL; - BB = NULL; - } -} Node; - -typedef struct CU_struct : Node_struct { - - string BBID; // BasicBlock Id where the CU appears in - - unsigned readDataSize; // number of bytes read from memory by the cu - unsigned writeDataSize; // number of bytes written into memory during the cu - unsigned instructionsCount; - - // basic block id & successor basic blocks for control dependence - vector successorCUs; // keeps IDs of control dependent CUs - string basicBlockName; - - set instructionsLineNumbers; - set readPhaseLineNumbers; - set writePhaseLineNumbers; - set returnInstructions; - - set localVariableNames; - set globalVariableNames; - - bool performsFileIO; - - // Map to record function call line numbers - map> callLineTofunctionMap; - - CU_struct() { - type = nodeTypes::cu; - readDataSize = 0; - writeDataSize = 0; - instructionsCount = 0; - // BB = NULL; - performsFileIO = false; - } - - void removeCU() { - CUIDCounter--; // if a CU does not contain any instruction, e.g. entry - // basic blocks, then remove it. - } - -} CU; - -// DPReduction - -struct instr_info_t { - std::string var_name_; - std::string var_type_; - int loop_line_nr_; - int file_id_; - llvm::StoreInst *store_inst_; - llvm::LoadInst *load_inst_; - char operation_ = ' '; -}; - -struct loop_info_t { - unsigned int line_nr_; - int file_id_; - llvm::Instruction *first_body_instr_; - std::string start_line; - std::string end_line; - std::string function_name; -}; - -// DPReduction end +*/ class DiscoPoP : public ModulePass { private: @@ -419,7 +308,7 @@ class DiscoPoP : public ModulePass { inline bool dp_reduction_loc_exists(llvm::DebugLoc const &loc) { return static_cast(loc); } unsigned dp_reduction_get_file_id(llvm::Function *func); bool dp_reduction_init_util(std::string fmap_path); - char dp_reduction_get_char_for_opcode(llvm::Instruction *instr); + char dp_reduction_get_char_for_opcode(llvm::Instruction *instr); //} // namespace bool dp_reduction_is_operand(llvm::Instruction *instr, llvm::Value *operand); int dp_reduction_get_op_order(char c); Type *dp_reduction_pointsToStruct(PointerType *PTy); @@ -439,24 +328,3 @@ class DiscoPoP : public ModulePass { // DPReduction end }; // end of class DiscoPoP -} // namespace - -char DiscoPoP::ID = 0; - -static RegisterPass X("DiscoPoP", "DiscoPoP: finding potential parallelism.", false, false); - -static void loadPass(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) { - PM.add(new LoopInfoWrapperPass()); - PM.add(new DiscoPoP()); -} - -static RegisterStandardPasses DiscoPoPLoader_Ox(PassManagerBuilder::EP_OptimizerLast, loadPass); -static RegisterStandardPasses DiscoPoPLoader_O0(PassManagerBuilder::EP_EnabledOnOptLevel0, loadPass); - -ModulePass *createDiscoPoPPass() { - if (DP_DEBUG) { - errs() << "create DiscoPoP \n"; - } - initializeLoopInfoWrapperPassPass(*PassRegistry::getPassRegistry()); - return new DiscoPoP(); -} diff --git a/DiscoPoP/Enums.hpp b/DiscoPoP/Enums.hpp new file mode 100644 index 000000000..daa714d8d --- /dev/null +++ b/DiscoPoP/Enums.hpp @@ -0,0 +1,15 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#pragma once + +enum nodeTypes { cu, func, loop, dummy }; \ No newline at end of file diff --git a/DiscoPoP/Globals.cpp b/DiscoPoP/Globals.cpp new file mode 100644 index 000000000..fc2668295 --- /dev/null +++ b/DiscoPoP/Globals.cpp @@ -0,0 +1,18 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "Globals.hpp" + +unsigned int CUIDCounter; +unsigned int bbDepCount; +bool defaultIsGlobalVariableValue; +std::int32_t fileID; \ No newline at end of file diff --git a/DiscoPoP/Globals.hpp b/DiscoPoP/Globals.hpp new file mode 100644 index 000000000..6dc5ce541 --- /dev/null +++ b/DiscoPoP/Globals.hpp @@ -0,0 +1,19 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#pragma once +#include + +extern unsigned int CUIDCounter; +extern unsigned int bbDepCount; +extern bool defaultIsGlobalVariableValue; +extern std::int32_t fileID; \ No newline at end of file diff --git a/DiscoPoP/RegisterPass.cpp b/DiscoPoP/RegisterPass.cpp new file mode 100644 index 000000000..835ea080b --- /dev/null +++ b/DiscoPoP/RegisterPass.cpp @@ -0,0 +1,33 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "DiscoPoP.hpp" + +char DiscoPoP::ID = 0; + +static RegisterPass X("DiscoPoP", "DiscoPoP: finding potential parallelism.", false, false); + +static void loadPass(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) { + PM.add(new LoopInfoWrapperPass()); + PM.add(new DiscoPoP()); +} + +static RegisterStandardPasses DiscoPoPLoader_Ox(PassManagerBuilder::EP_OptimizerLast, loadPass); +static RegisterStandardPasses DiscoPoPLoader_O0(PassManagerBuilder::EP_EnabledOnOptLevel0, loadPass); + +ModulePass *createDiscoPoPPass() { + if (DP_DEBUG) { + errs() << "create DiscoPoP \n"; + } + initializeLoopInfoWrapperPassPass(*PassRegistry::getPassRegistry()); + return new DiscoPoP(); +} \ No newline at end of file diff --git a/DiscoPoP/RegisterPass.hpp b/DiscoPoP/RegisterPass.hpp new file mode 100644 index 000000000..77313504e --- /dev/null +++ b/DiscoPoP/RegisterPass.hpp @@ -0,0 +1,20 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +extern RegisterPass X("DiscoPoP", "DiscoPoP: finding potential parallelism.", false, false); + +void loadPass(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM); + +static RegisterStandardPasses DiscoPoPLoader_Ox(PassManagerBuilder::EP_OptimizerLast, loadPass); +static RegisterStandardPasses DiscoPoPLoader_O0(PassManagerBuilder::EP_EnabledOnOptLevel0, loadPass); + +ModulePass *createDiscoPoPPass(); \ No newline at end of file diff --git a/DiscoPoP/Structs.hpp b/DiscoPoP/Structs.hpp new file mode 100644 index 000000000..6cd0f124b --- /dev/null +++ b/DiscoPoP/Structs.hpp @@ -0,0 +1,125 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#pragma once + +#include "Enums.hpp" +#include "Globals.hpp" + +typedef struct Variable_struct { + string name; + string type; + string defLine; + string isArray; + bool readAccess; + bool writeAccess; + string sizeInBytes; + + Variable_struct(const Variable_struct &other) + : name(other.name), type(other.type), defLine(other.defLine), readAccess(other.readAccess), + writeAccess(other.writeAccess), sizeInBytes(other.sizeInBytes) {} + + Variable_struct(string n, string t, string d, bool readAccess, bool writeAccess, string sizeInBytes) + : name(n), type(t), defLine(d), readAccess(readAccess), writeAccess(writeAccess), sizeInBytes(sizeInBytes) {} + + // We have a set of this struct. The set doesn't know how to order the + // elements. + inline bool operator<(const Variable_struct &rhs) const { return name < rhs.name; } + + inline bool operator>(const Variable_struct &rhs) const { return name > rhs.name; } + +} Variable; + +typedef struct Node_struct { + string ID; + nodeTypes type; + int startLine; + int endLine; + BasicBlock *BB; + + // Only for func type + string name; + vector argumentsList; + set returnLines; + + vector childrenNodes; + Node_struct *parentNode; + + // isRecursive function (Mo 5.11.2019) + string recursiveFunctionCall = ""; + + Node_struct() { + ID = to_string(fileID) + ":" + to_string(CUIDCounter++); + parentNode = NULL; + BB = NULL; + } +} Node; + +typedef struct CU_struct : Node_struct { + + string BBID; // BasicBlock Id where the CU appears in + + unsigned readDataSize; // number of bytes read from memory by the cu + unsigned writeDataSize; // number of bytes written into memory during the cu + unsigned instructionsCount; + + // basic block id & successor basic blocks for control dependence + vector successorCUs; // keeps IDs of control dependent CUs + string basicBlockName; + + set instructionsLineNumbers; + set readPhaseLineNumbers; + set writePhaseLineNumbers; + set returnInstructions; + + set localVariableNames; + set globalVariableNames; + + bool performsFileIO; + + // Map to record function call line numbers + map> callLineTofunctionMap; + + CU_struct() { + type = nodeTypes::cu; + readDataSize = 0; + writeDataSize = 0; + instructionsCount = 0; + // BB = NULL; + performsFileIO = false; + } + + void removeCU() { + CUIDCounter--; // if a CU does not contain any instruction, e.g. entry + // basic blocks, then remove it. + } + +} CU; + +struct instr_info_t { + std::string var_name_; + std::string var_type_; + int loop_line_nr_; + int file_id_; + llvm::StoreInst *store_inst_; + llvm::LoadInst *load_inst_; + char operation_ = ' '; +}; + +struct loop_info_t { + unsigned int line_nr_; + int file_id_; + llvm::Instruction *first_body_instr_; + std::string start_line; + std::string end_line; + std::string function_name; +}; \ No newline at end of file diff --git a/DiscoPoP/dp_reduction/CFA.cpp b/DiscoPoP/dp_reduction/CFA.cpp new file mode 100644 index 000000000..b6e008f38 --- /dev/null +++ b/DiscoPoP/dp_reduction/CFA.cpp @@ -0,0 +1,123 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../DiscoPoP.hpp" + +std::string DiscoPoP::dp_reduction_CFA(Function &F, llvm::Loop *L, int file_id) { + std::string lid = "LOOPENDNOTFOUND"; + SmallVector ExitBlocks; + for (Function::iterator BB = F.begin(), BE = F.end(); BB != BE; ++BB) { + BasicBlock *tmpBB = &*BB; + ExitBlocks.clear(); + + // Get the closest loop where tmpBB lives in. + // (L == NULL) if tmpBB is not in any loop. + + // Check if tmpBB is the loop header (.cond) block. + if (L != NULL) { + StringRef loopType = tmpBB->getName().split('.').first; + + // If tmpBB is the header block, get the exit blocks of the loop. + if (L->hasDedicatedExits()) { + // loop exits are in canonical form + L->getUniqueExitBlocks(ExitBlocks); + } else { + // loop exits are NOT in canonical form + L->getExitBlocks(ExitBlocks); + } + + if (ExitBlocks.size() == 0) { + continue; + } + + // When loop has break statement inside, exit blocks may contain + // the if-else block containing the break. Since we always want + // to find the real exit (.end) block, we need to check the + // successors of the break statement(s). + SmallVector RealExitBlocks; + + for (SmallVectorImpl::iterator EI = ExitBlocks.begin(), END = ExitBlocks.end(); EI != END; ++EI) { + StringRef exitType = (*EI)->getName().split('.').first; + if (exitType.equals(loopType) && ((*EI)->getName().find("end") != string::npos) && + (std::find(RealExitBlocks.begin(), RealExitBlocks.end(), *EI) == RealExitBlocks.end())) { + RealExitBlocks.push_back(*EI); + } else { + // Changed TerminatorInst to Instruction + Instruction *TI = (*EI)->getTerminator(); + assert(TI != NULL && "Exit block is not well formed!"); + unsigned int numSucc = TI->getNumSuccessors(); + for (unsigned int i = 0; i < numSucc; ++i) { + BasicBlock *succ = TI->getSuccessor(i); + exitType = succ->getName().split('.').first; + if (exitType.equals(loopType) && (succ->getName().find("end") != string::npos) && + (std::find(RealExitBlocks.begin(), RealExitBlocks.end(), succ) == RealExitBlocks.end())) { + RealExitBlocks.push_back(succ); + } + } + } + } + + if (RealExitBlocks.size() == 0) { + continue; + } + + // Check if entry block and exit block(s) have valid LID. + bool hasValidExit = false; + for (SmallVectorImpl::iterator EI = RealExitBlocks.begin(), END = RealExitBlocks.end(); EI != END; + ++EI) { + hasValidExit = dp_reduction_sanityCheck(*EI, file_id); + if (hasValidExit == true) + break; + } + + if (hasValidExit) { + for (SmallVectorImpl::iterator EI = RealExitBlocks.begin(), END = RealExitBlocks.end(); EI != END; + ++EI) { + BasicBlock *currentBB = *EI; + vector args; + LID lid = 0; + + for (BasicBlock::iterator BI = currentBB->begin(), EI = currentBB->end(); BI != EI; ++BI) { + lid = dp_reduction_getLID(&*BI, file_id); + uint64_t ulid = (uint64_t)lid; + if (ulid != 0) { + return to_string(ulid % 16384); + } + } + } + } + } + } + if (lid == "LOOPENDNOTFOUND") { + if (MDNode *LoopID = L->getLoopID()) { + DebugLoc Start; + // We use the first DebugLoc in the header as the start location of the + // loop and if there is a second DebugLoc in the header we use it as end + // location of the loop. + bool foundEnd = false; + for (unsigned i = 1, ie = LoopID->getNumOperands(); i < ie; ++i) { + if (DILocation *DIL = dyn_cast(LoopID->getOperand(i))) { + if (!Start) { + if (foundEnd) { + lid = to_string(DebugLoc(DIL)->getLine()); + + break; + } else { + foundEnd = true; + } + } + } + } + } + } + return lid; +} diff --git a/DiscoPoP/dp_reduction/determine_variable_name.cpp b/DiscoPoP/dp_reduction/determine_variable_name.cpp new file mode 100644 index 000000000..533d40b2d --- /dev/null +++ b/DiscoPoP/dp_reduction/determine_variable_name.cpp @@ -0,0 +1,98 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../DiscoPoP.hpp" + +string DiscoPoP::dp_reduction_determineVariableName(Instruction *I, map *trueVarNamesFromMetadataMap) { + + assert(I && "Instruction cannot be NULL \n"); + int index = isa(I) ? 1 : 0; + Value *operand = I->getOperand(index); + + IRBuilder<> builder(I); + + if (operand == NULL) { + string retVal = getOrInsertVarName_static("", builder); + if (trueVarNamesFromMetadataMap->find(retVal) == trueVarNamesFromMetadataMap->end()) { + return retVal; // not found + } else { + return (*trueVarNamesFromMetadataMap)[retVal]; // found + } + } + + if (operand->hasName()) { + //// we've found a global variable + if (isa(*operand)) { + string retVal = string(operand->getName()); + if (trueVarNamesFromMetadataMap->find(retVal) == trueVarNamesFromMetadataMap->end()) { + return retVal; // not found + } else { + return (*trueVarNamesFromMetadataMap)[retVal]; // found + } + } + if (isa(*operand)) { + GetElementPtrInst *gep = cast(operand); + Value *ptrOperand = gep->getPointerOperand(); + PointerType *PTy = cast(ptrOperand->getType()); + + // we've found a struct/class + Type *structType = dp_reduction_pointsToStruct(PTy); + if (structType && gep->getNumOperands() > 2) { + Value *constValue = gep->getOperand(2); + if (constValue && isa(*constValue)) { + ConstantInt *idxPtr = cast(gep->getOperand(2)); + uint64_t memberIdx = *(idxPtr->getValue().getRawData()); + if (!(cast(structType))->isLiteral()) { + string strName(structType->getStructName().data()); + map::iterator it = Structs.find(strName); + if (it != Structs.end()) { + std::string ret = findStructMemberName_static(it->second, memberIdx, builder); + if (ret.size() > 0) { + string retVal = ret; + if (trueVarNamesFromMetadataMap->find(retVal) == trueVarNamesFromMetadataMap->end()) { + return retVal; // not found + } else { + return (*trueVarNamesFromMetadataMap)[retVal]; // found + } + } else { + string retVal = getOrInsertVarName_static("", builder); + if (trueVarNamesFromMetadataMap->find(retVal) == trueVarNamesFromMetadataMap->end()) { + return retVal; // not found + } else { + return (*trueVarNamesFromMetadataMap)[retVal]; // found + } + } + } + } + } + } + + // we've found an array + if (PTy->getPointerElementType()->getTypeID() == Type::ArrayTyID && isa(*ptrOperand)) { + return dp_reduction_determineVariableName((Instruction *)ptrOperand, trueVarNamesFromMetadataMap); + } + return dp_reduction_determineVariableName((Instruction *)gep, trueVarNamesFromMetadataMap); + } + string retVal = string(operand->getName().data()); + if (trueVarNamesFromMetadataMap->find(retVal) == trueVarNamesFromMetadataMap->end()) { + return retVal; // not found + } else { + return (*trueVarNamesFromMetadataMap)[retVal]; // found + } + } + + if (isa(*operand) || isa(*operand)) { + return dp_reduction_determineVariableName((Instruction *)(operand), trueVarNamesFromMetadataMap); + } + // if we cannot determine the name, then return * + return "*"; +} diff --git a/DiscoPoP/dp_reduction/determine_variable_type.cpp b/DiscoPoP/dp_reduction/determine_variable_type.cpp new file mode 100644 index 000000000..0eca38ccb --- /dev/null +++ b/DiscoPoP/dp_reduction/determine_variable_type.cpp @@ -0,0 +1,52 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../DiscoPoP.hpp" + +string DiscoPoP::dp_reduction_determineVariableType(Instruction *I) { + string s = ""; + string type_str; + int index = isa(I) ? 1 : 0; + raw_string_ostream rso(type_str); + (*((I->getOperand(index))->getType())).print(rso); + + Value *operand = I->getOperand(index); + + if (operand->hasName()) { + if (isa(*operand)) { + GetElementPtrInst *gep = cast(operand); + Value *ptrOperand = gep->getPointerOperand(); + PointerType *PTy = cast(ptrOperand->getType()); + // we've found a struct/class + Type *structType = dp_reduction_pointsToStruct(PTy); + if (structType && gep->getNumOperands() > 2) { + s = "STRUCT,"; + } + // we've found an array + if (PTy->getPointerElementType()->getTypeID() == Type::ArrayTyID) { + s = "ARRAY,"; + } else { + // check if previous instruction is a GEP aswell. If so, an Array has + // been found (e.g. double**) + Value *prevInst = cast(gep)->getOperand(0); + if (isa(prevInst)) { + s = "ARRAY,"; + } else if (prevInst->getType()->isPointerTy()) { + s = "ARRAY,"; + } + } + } + } + + s = s + rso.str(); + return s; +} diff --git a/DiscoPoP/dp_reduction/find_reduction_instr.cpp b/DiscoPoP/dp_reduction/find_reduction_instr.cpp new file mode 100644 index 000000000..4992c7ea4 --- /dev/null +++ b/DiscoPoP/dp_reduction/find_reduction_instr.cpp @@ -0,0 +1,40 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../DiscoPoP.hpp" + +// returns the reduction instruction where 'val' is the operand if it can find +// such an operation +llvm::Instruction *DiscoPoP::dp_reduction_find_reduction_instr(llvm::Value *val) { + if (!val || !llvm::isa(val)) { + return nullptr; + } + llvm::Instruction *instr = llvm::cast(val); + unsigned opcode = instr->getOpcode(); + char c = dp_reduction_get_char_for_opcode(instr); + if (c != ' ') { + return instr; + } else if (opcode == llvm::Instruction::Load) { + llvm::Instruction *prev_use = dp_reduction_get_prev_use(instr, instr->getOperand(0)); + return dp_reduction_find_reduction_instr(prev_use); + } else if (opcode == llvm::Instruction::Store) { + return dp_reduction_find_reduction_instr(instr->getOperand(0)); + } + // enter recursion if the instruction has only a single operand to accomodate + // for type conversions etc. + if (instr->getNumOperands() == 1) { + // unpack instruction + return dp_reduction_find_reduction_instr(instr->getOperand(0)); + } + // no reduction instruction found + return nullptr; +} \ No newline at end of file diff --git a/DiscoPoP/dp_reduction/get_load_instr.cpp b/DiscoPoP/dp_reduction/get_load_instr.cpp new file mode 100644 index 000000000..9cf91a92f --- /dev/null +++ b/DiscoPoP/dp_reduction/get_load_instr.cpp @@ -0,0 +1,79 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../DiscoPoP.hpp" + +// Finds the load instruction that actually loads the value from the address +// 'load_val'. +llvm::Instruction *DiscoPoP::dp_reduction_get_load_instr(llvm::Value *load_val, llvm::Instruction *cur_instr, + std::vector &reduction_operations) { + if (!load_val || !cur_instr) + return nullptr; + if (llvm::isa(cur_instr)) { + // Does the current instruction already load the value from the correct + // address? If that is the case, return it. + llvm::Value *val = cur_instr->getOperand(0); + if (val == load_val) + return cur_instr; + + // The current instruction does not load the value from the address of + // 'load_val'. But it might load the value from a variable where 'load_val' + // is stored in, so find the previous use of the source operand. + llvm::Instruction *prev_use = dp_reduction_get_prev_use(cur_instr, val); + if (prev_use) { + if (llvm::isa(prev_use)) { + return dp_reduction_get_load_instr(load_val, prev_use, reduction_operations); + } else if (llvm::isa(prev_use)) { + llvm::GetElementPtrInst *ptr_instr = llvm::cast(prev_use); + llvm::Value *points_to = dp_reduction_points_to_var(ptr_instr); + if (points_to == load_val) { + return cur_instr; + } else { + bool found = static_cast(dp_reduction_get_load_instr( + load_val, llvm::dyn_cast(points_to), reduction_operations)); + return (found) ? cur_instr : nullptr; + } + } else { + bool found = static_cast(dp_reduction_get_load_instr(load_val, prev_use, reduction_operations)); + return (found) ? cur_instr : nullptr; + } + } else { + return nullptr; + } + } + + unsigned opcode = cur_instr->getOpcode(); + char c = dp_reduction_get_char_for_opcode(cur_instr); + if (c != ' ') { + reduction_operations.push_back(c); + } + + // The current instruction is not a load instruction. Follow the operands + // of the current instruction recursively until the desired load instruction + // is reached. + llvm::Instruction *result = nullptr; + for (unsigned int i = 0; i != cur_instr->getNumOperands(); ++i) { + llvm::Value *operand = cur_instr->getOperand(i); + if (llvm::isa(operand)) { + result = dp_reduction_get_load_instr(load_val, llvm::cast(operand), reduction_operations); + if (result) { + break; + } + } + } + + if (!result && c != ' ') { + reduction_operations.pop_back(); + } + + return result; +} diff --git a/DiscoPoP/dp_reduction/get_reduction_instr.cpp b/DiscoPoP/dp_reduction/get_reduction_instr.cpp new file mode 100644 index 000000000..fb817f4a2 --- /dev/null +++ b/DiscoPoP/dp_reduction/get_reduction_instr.cpp @@ -0,0 +1,50 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../DiscoPoP.hpp" + +// Retrieves the reduction operation for the operand that is stored by the +// 'store_instr' (if such a reduction operation exists). +// The parameter 'load_instr' will point to the load instruction that actually +// loads the value (if such a load instruction exists). +llvm::Instruction *DiscoPoP::dp_reduction_get_reduction_instr(llvm::Instruction *store_instr, + llvm::Instruction **load_instr) { + // find the reduction operation for the source operand of the 'store_instr' + llvm::Instruction *reduction_instr = dp_reduction_find_reduction_instr(store_instr->getOperand(0)); + if (!reduction_instr) { + return nullptr; + } + // Now find the destination address of the store instruction. + // After that, search the load instruction that loads this value and store a + // pointer to it in 'load_instr'. + llvm::Value *store_dst = dp_reduction_get_var_rec(store_instr->getOperand(1)); + if (store_dst) { + std::vector reduction_operations; + *load_instr = dp_reduction_get_load_instr(store_dst, reduction_instr, reduction_operations); + // { *, / } > { +, - } > { & } > { ^ } > { | } + if (reduction_operations.size() > 1) { + int order = dp_reduction_get_op_order(reduction_operations[0]); + for (size_t i = 1; i != reduction_operations.size(); ++i) { + int order_i = dp_reduction_get_op_order(reduction_operations[i]); + if (order_i > order) { + *load_instr = nullptr; + return nullptr; + } + } + } + if (*load_instr) { + return reduction_instr; + } + } + + return nullptr; +} \ No newline at end of file diff --git a/DiscoPoP/dp_reduction/get_var.cpp b/DiscoPoP/dp_reduction/get_var.cpp new file mode 100644 index 000000000..f57ad1ac2 --- /dev/null +++ b/DiscoPoP/dp_reduction/get_var.cpp @@ -0,0 +1,47 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../DiscoPoP.hpp" + +llvm::Value *DiscoPoP::dp_reduction_get_var_rec(llvm::Value *val) { + if (!val) + return nullptr; + + if (llvm::isa(val) || llvm::isa(val)) { + return val; + } + if (llvm::isa(val)) { + llvm::GetElementPtrInst *elem_ptr_instr = llvm::cast(val); + + // struct member reductions are not supported by OpenMP + llvm::Value *points_to = dp_reduction_points_to_var(elem_ptr_instr); + llvm::AllocaInst *a_instr = llvm::dyn_cast(points_to); + llvm::Type *type = (a_instr) ? a_instr->getAllocatedType() : points_to->getType(); + if (type->isStructTy()) { + return nullptr; + } + + return dp_reduction_get_var_rec(elem_ptr_instr->getPointerOperand()); + } + if (llvm::isa(val)) { + llvm::LoadInst *load_instr = llvm::cast(val); + return dp_reduction_get_var_rec(load_instr->getOperand(0)); + } + + return nullptr; +} + +// Get the value that is stored or loaded by a store / load instruction. +llvm::Value *DiscoPoP::dp_reduction_get_var(llvm::Instruction *instr) { + unsigned index = (llvm::isa(instr)) ? 0 : 1; + return dp_reduction_get_var_rec(instr->getOperand(index)); +} \ No newline at end of file diff --git a/DiscoPoP/dp_reduction/insert_functions.cpp b/DiscoPoP/dp_reduction/insert_functions.cpp new file mode 100644 index 000000000..6b9d5d8d3 --- /dev/null +++ b/DiscoPoP/dp_reduction/insert_functions.cpp @@ -0,0 +1,73 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../DiscoPoP.hpp" + +// Inserts calls to allow for dynamic analysis of the loops. +void DiscoPoP::dp_reduction_insert_functions() { + + // insert function calls to monitor the variable's load and store operations + for (auto const &instruction : instructions_) { + int store_line = instruction.store_inst_->getDebugLoc().getLine(); + + // output information about the reduction variables + *reduction_file << " FileID : " << instruction.file_id_; + *reduction_file << " Loop Line Number : " << instruction.loop_line_nr_; + *reduction_file << " Reduction Line Number : " << to_string(store_line); + *reduction_file << " Variable Name : " << instruction.var_name_; + *reduction_file << " Operation Name : " << instruction.operation_ << "\n"; + } + + // insert function calls to monitor loop iterations + std::ofstream loop_metadata_file; + std::string tmp(getenv("DOT_DISCOPOP_PROFILER")); + tmp += "/loop_meta.txt"; + loop_metadata_file.open(tmp.data()); + int loop_id = 1; + llvm::Type *loop_incr_fn_arg_type = llvm::Type::getInt32Ty(*ctx_); + llvm::ArrayRef loop_incr_fn_args(loop_incr_fn_arg_type); + llvm::FunctionType *loop_incr_fn_type = + llvm::FunctionType::get(llvm::Type::getVoidTy(*ctx_), loop_incr_fn_args, false); + FunctionCallee incr_loop_counter_callee = module_->getOrInsertFunction("__dp_loop_incr", loop_incr_fn_type); + + for (auto const &loop_info : loops_) { + llvm::Value *val = llvm::ConstantInt::get(llvm::Type::getInt32Ty(*ctx_), loop_id); + llvm::ArrayRef args(val); + llvm::CallInst::Create(incr_loop_counter_callee, args, "", loop_info.first_body_instr_); + loop_metadata_file << loop_info.file_id_ << " "; + loop_metadata_file << loop_id++ << " "; + loop_metadata_file << loop_info.line_nr_ << "\n"; + } + loop_metadata_file.close(); + + // add a function to output the final data + // dp_loop_output + llvm::FunctionType *output_fn_type = llvm::FunctionType::get(llvm::Type::getVoidTy(*ctx_), false); + FunctionCallee loop_counter_output_callee = module_->getOrInsertFunction("__dp_loop_output", output_fn_type); + FunctionCallee cu_taken_branch_counter_output_callee = + module_->getOrInsertFunction("__dp_taken_branch_counter_output", output_fn_type); + llvm::Function *main_fn = module_->getFunction("main"); + if (main_fn) { + for (auto it = llvm::inst_begin(main_fn); it != llvm::inst_end(main_fn); ++it) { + if (llvm::isa(&(*it))) { + llvm::IRBuilder<> ir_builder(&(*it)); + ir_builder.CreateCall(loop_counter_output_callee); + if (DP_BRANCH_TRACKING) { + ir_builder.CreateCall(cu_taken_branch_counter_output_callee); + } + break; + } + } + } else { + llvm::errs() << "Warning : Could not find a main function\n"; + } +} \ No newline at end of file diff --git a/DiscoPoP/dp_reduction/utils.cpp b/DiscoPoP/dp_reduction/utils.cpp new file mode 100644 index 000000000..6831d5911 --- /dev/null +++ b/DiscoPoP/dp_reduction/utils.cpp @@ -0,0 +1,236 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../DiscoPoP.hpp" + +unsigned DiscoPoP::dp_reduction_get_file_id(llvm::Function *func) { + unsigned file_id = 0; + + // get the filepath of this function + char abs_path[PATH_MAX] = {'\0'}; + for (auto bb_it = func->begin(); bb_it != func->end(); ++bb_it) { + for (auto instr_it = bb_it->begin(); instr_it != bb_it->end(); ++instr_it) { + llvm::MDNode *node = instr_it->getMetadata("dbg"); + if (!node) + continue; + + llvm::DILocation *di_loc = llvm::dyn_cast(node); + llvm::StringRef filename = di_loc->getFilename(); + llvm::StringRef directory = di_loc->getDirectory(); + + char *success = realpath((directory.str() + "/" + filename.str()).c_str(), abs_path); + if (!success) { + realpath(filename.str().c_str(), abs_path); + } + + break; + } + if (abs_path[0] != '\0') + break; + } + + if (abs_path[0] != '\0') { + auto it = path_to_id_.find(std::string(abs_path)); + if (it != path_to_id_.end()) { + file_id = it->second; + } else { + } + } + + return file_id; +} + +// finds the previous use of 'val' +llvm::Instruction *DiscoPoP::dp_reduction_get_prev_use(llvm::Instruction *instr, llvm::Value *val) { + if (!instr) + return nullptr; + + auto instr_users = val->users(); + bool instr_found = false; + for (auto user : instr_users) { + if (!llvm::isa(user)) { + continue; + } + llvm::Instruction *usr_instr = llvm::cast(user); + + if (instr_found) { + return usr_instr; + } else if (usr_instr == instr) { + instr_found = true; + continue; + } + } + return llvm::dyn_cast(val); +} + +int DiscoPoP::dp_reduction_get_op_order(char c) { + if (c == '*' || c == '/') + return 5; + if (c == '+' || c == '-') + return 4; + if (c == '&') + return 3; + if (c == '^') + return 2; + if (c == '|') + return 1; + return 0; +} + +Type *DiscoPoP::dp_reduction_pointsToStruct(PointerType *PTy) { + assert(PTy); + Type *structType = PTy; + if (PTy->getTypeID() == Type::PointerTyID) { + while (structType->getTypeID() == Type::PointerTyID) { + structType = cast(structType)->getPointerElementType(); + } + } + return structType->getTypeID() == Type::StructTyID ? structType : NULL; +} + +string DiscoPoP::findStructMemberName_static(MDNode *structNode, unsigned idx, IRBuilder<> &builder) { + assert(structNode); + assert(structNode->getOperand(10)); + MDNode *memberListNodes = cast(structNode->getOperand(10)); + if (idx < memberListNodes->getNumOperands()) { + assert(memberListNodes->getOperand(idx)); + MDNode *member = cast(memberListNodes->getOperand(idx)); + if (member->getOperand(3)) { + getOrInsertVarName_static(dyn_cast(member->getOperand(3))->getString().str(), builder); + return dyn_cast(member->getOperand(3))->getString().str(); + } + } + return NULL; +} + +// returns the value that the GetElementPtrInst ultimately points to +llvm::Value *DiscoPoP::dp_reduction_points_to_var(llvm::GetElementPtrInst *instr) { + llvm::Value *points_to = nullptr; + while (instr) { + points_to = instr->getPointerOperand(); + instr = llvm::dyn_cast(points_to); + } + return points_to; +} + +// Encode the fileID and line number of BI as LID. +// This is needed to support multiple files in a project. +LID DiscoPoP::dp_reduction_getLID(Instruction *BI, int32_t &fileID) { + int32_t lno; + + const DebugLoc &location = BI->getDebugLoc(); + if (location) { + lno = BI->getDebugLoc().getLine(); + } else { + lno = 0; + } + + if (lno == 0) { + return 0; + } + LID lid = lno; + return lid; +} + +bool DiscoPoP::dp_reduction_sanityCheck(BasicBlock *BB, int file_id) { + LID lid; + for (BasicBlock::iterator BI = BB->begin(), EI = BB->end(); BI != EI; ++BI) { + lid = dp_reduction_getLID(&*BI, file_id); + if (lid > 0) { + return true; + } + } + return false; +} + +// returns a char describing the opcode, e.g. '+' for Add or FAdd +// switches + and - if a negative constant is added or subtracted +//(mainly used to support -- as reduction operation, might be implemented as +//'add -1') +char DiscoPoP::dp_reduction_get_char_for_opcode(llvm::Instruction *instr) { + unsigned opcode = instr->getOpcode(); + + if (opcode == llvm::Instruction::Add || opcode == llvm::Instruction::FAdd) { + bool operand_is_negative_constant = false; + if (instr->getNumOperands() >= 1) { + Value *rhs_value = instr->getOperand(1); + if (isa(rhs_value)) { + operand_is_negative_constant = cast(rhs_value)->isNegative(); + } + } + + if (operand_is_negative_constant) + return '-'; + else + return '+'; + } + if (opcode == llvm::Instruction::Sub || opcode == llvm::Instruction::FSub) { + bool operand_is_negative_constant = false; + if (instr->getNumOperands() >= 1) { + Value *rhs_value = instr->getOperand(1); + if (isa(rhs_value)) { + operand_is_negative_constant = cast(rhs_value)->isNegative(); + } + } + + if (operand_is_negative_constant) + return '+'; + else + return '-'; + } + if (opcode == llvm::Instruction::Mul || opcode == llvm::Instruction::FMul) + return '*'; + if (opcode == llvm::Instruction::And) + return '&'; + if (opcode == llvm::Instruction::Or) + return '|'; + if (opcode == llvm::Instruction::Xor) + return '^'; + return ' '; +} + +// return true if 'operand' is an operand of the instruction 'instr' +bool DiscoPoP::dp_reduction_is_operand(llvm::Instruction *instr, llvm::Value *operand) { + unsigned num_operands = instr->getNumOperands(); + for (unsigned i = 0; i < num_operands; ++i) { + if (instr->getOperand(i) == operand) + return true; + } + return false; +} + +bool DiscoPoP::dp_reduction_init_util(std::string fmap_path) { + std::ifstream fmap_file; + fmap_file.open(fmap_path.c_str()); + if (fmap_file.fail()) { + std::cout << "Opening FileMapping failed: " << strerror(errno) << "\n"; + } + if (!fmap_file.is_open()) { + return false; + } + + std::string line; + while (std::getline(fmap_file, line)) { + char filename[512] = {'\0'}; + int file_id = 0; + + int cnt = sscanf(line.c_str(), "%d\t%s", &file_id, filename); + if (cnt == 2) { + + path_to_id_.emplace(std::string(filename), file_id); + } + } + + fmap_file.close(); + + return true; +} diff --git a/DiscoPoP/Graph.hpp b/DiscoPoP/hybrid_analysis/Graph.hpp similarity index 100% rename from DiscoPoP/Graph.hpp rename to DiscoPoP/hybrid_analysis/Graph.hpp diff --git a/DiscoPoP/InstructionCFG.cpp b/DiscoPoP/hybrid_analysis/InstructionCFG.cpp similarity index 100% rename from DiscoPoP/InstructionCFG.cpp rename to DiscoPoP/hybrid_analysis/InstructionCFG.cpp diff --git a/DiscoPoP/InstructionCFG.hpp b/DiscoPoP/hybrid_analysis/InstructionCFG.hpp similarity index 100% rename from DiscoPoP/InstructionCFG.hpp rename to DiscoPoP/hybrid_analysis/InstructionCFG.hpp diff --git a/DiscoPoP/InstructionDG.cpp b/DiscoPoP/hybrid_analysis/InstructionDG.cpp similarity index 100% rename from DiscoPoP/InstructionDG.cpp rename to DiscoPoP/hybrid_analysis/InstructionDG.cpp diff --git a/DiscoPoP/InstructionDG.hpp b/DiscoPoP/hybrid_analysis/InstructionDG.hpp similarity index 100% rename from DiscoPoP/InstructionDG.hpp rename to DiscoPoP/hybrid_analysis/InstructionDG.hpp diff --git a/DiscoPoP/initialization/initializeBBDepCounter.cpp b/DiscoPoP/initialization/initializeBBDepCounter.cpp new file mode 100644 index 000000000..4afc1ecd6 --- /dev/null +++ b/DiscoPoP/initialization/initializeBBDepCounter.cpp @@ -0,0 +1,25 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../DiscoPoP.hpp" + +void DiscoPoP::initializeBBDepCounter() { + + std::string BBDepCounterFile(getenv("DOT_DISCOPOP_PROFILER")); + BBDepCounterFile += "/DP_BBDepCounter.txt"; + if (dputil::fexists(BBDepCounterFile)) { + std::fstream inBBDepCounter(BBDepCounterFile, std::ios_base::in); + ; + inBBDepCounter >> bbDepCount; + inBBDepCounter.close(); + } +} \ No newline at end of file diff --git a/DiscoPoP/initialization/initializeCUIDCounter.cpp b/DiscoPoP/initialization/initializeCUIDCounter.cpp new file mode 100644 index 000000000..bbc755e10 --- /dev/null +++ b/DiscoPoP/initialization/initializeCUIDCounter.cpp @@ -0,0 +1,24 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../DiscoPoP.hpp" + +void DiscoPoP::initializeCUIDCounter() { + std::string CUCounterFile(getenv("DOT_DISCOPOP_PROFILER")); + CUCounterFile += "/DP_CUIDCounter.txt"; + if (dputil::fexists(CUCounterFile)) { + std::fstream inCUIDCounter(CUCounterFile, std::ios_base::in); + ; + inCUIDCounter >> CUIDCounter; + inCUIDCounter.close(); + } +} \ No newline at end of file diff --git a/DiscoPoP/instrumentation/high_level/instrumentFunction.cpp b/DiscoPoP/instrumentation/high_level/instrumentFunction.cpp new file mode 100644 index 000000000..2c7f43a75 --- /dev/null +++ b/DiscoPoP/instrumentation/high_level/instrumentFunction.cpp @@ -0,0 +1,31 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../../DiscoPoP.hpp" + +// iterates over all loops in a function and calls 'instrument_loop' for each +// one +void DiscoPoP::instrument_function(llvm::Function *function, map *trueVarNamesFromMetadataMap) { + + // get the corresponding file id + int32_t tmp_file_id; + determineFileID(*function, tmp_file_id); + if (tmp_file_id == 0) { + return; + } + + llvm::LoopInfo &loop_info = getAnalysis(*function).getLoopInfo(); + + for (auto loop_it = loop_info.begin(); loop_it != loop_info.end(); ++loop_it) { + instrument_loop(*function, tmp_file_id, *loop_it, loop_info, trueVarNamesFromMetadataMap); + } +} \ No newline at end of file diff --git a/DiscoPoP/instrumentation/high_level/instrumentLoop.cpp b/DiscoPoP/instrumentation/high_level/instrumentLoop.cpp new file mode 100644 index 000000000..7f6357d31 --- /dev/null +++ b/DiscoPoP/instrumentation/high_level/instrumentLoop.cpp @@ -0,0 +1,212 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../../DiscoPoP.hpp" + +// Goes through all instructions in a loop and determines if they might be +// suitable for reduction. +// An entry is added to the 'loops_' vector and for each suitable instruction, +// an entry is added to the 'instructions_' vector. +void DiscoPoP::instrument_loop(Function &F, int file_id, llvm::Loop *loop, LoopInfo &LI, + map *trueVarNamesFromMetadataMap) { + + auto loc = loop->getStartLoc(); + if (!dp_reduction_loc_exists(loc)) { + return; + } + + auto basic_blocks = loop->getBlocks(); + if (basic_blocks.size() < 3) { + return; + } + // add an entry to the 'loops_' vector + loop_info_t loop_info; + loop_info.line_nr_ = loc.getLine(); + loop_info.file_id_ = file_id; + loop_info.first_body_instr_ = &(*basic_blocks[1]->begin()); + + std::string loopEndLine = dp_reduction_CFA(F, loop, file_id); + loop_info.end_line = loopEndLine; + loop_info.function_name = string((basic_blocks[1]->getParent()->getName())); + loops_.push_back(loop_info); + + // call 'instrument_loop' on all its subloops + auto const sub_loops = loop->getSubLoops(); + for (auto loop_it = sub_loops.begin(); loop_it != sub_loops.end(); ++loop_it) { + instrument_loop(F, file_id, *loop_it, LI, trueVarNamesFromMetadataMap); + } + // The key corresponds to the variable that is loaded / stored. + // The value points to the actual load / store instruction. + std::map load_instructions; + std::map store_instructions; + + // Scan all instructions in the loop's basic blocks to find the load and + // store instructions. + for (size_t i = 0; i < basic_blocks.size(); ++i) { + llvm::BasicBlock *const bb = basic_blocks[i]; + + std::string bb_name = bb->getName().str(); + if ((std::strncmp("for.inc", bb_name.c_str(), 7) == 0) || (std::strncmp("for.cond", bb_name.c_str(), 8) == 0)) { + continue; + } + + for (auto instr_it = bb->begin(); instr_it != bb->end(); ++instr_it) { + llvm::Instruction *instr = &(*instr_it); + + auto opcode = instr->getOpcode(); + if (opcode != llvm::Instruction::Store && opcode != llvm::Instruction::Load) { + continue; + } + + // Add an entry to the corresponding map or invalidate an already + // existing entry, if the same instruction is executed on multiple + // lines. + llvm::Value *operand = dp_reduction_get_var(instr); + if (operand) { + std::map *map_ptr = + (opcode == llvm::Instruction::Store) ? &store_instructions : &load_instructions; + if (!map_ptr->insert(std::make_pair(operand, instr)).second) { + if ((*map_ptr)[operand]) { + llvm::DebugLoc new_loc = instr->getDebugLoc(); + llvm::DebugLoc old_loc = (*map_ptr)[operand]->getDebugLoc(); + + if (!dp_reduction_loc_exists(new_loc) || !dp_reduction_loc_exists(old_loc)) { + (*map_ptr)[operand] = nullptr; + } else if (new_loc.getLine() != old_loc.getLine()) { + (*map_ptr)[operand] = nullptr; + } + } + } + } + } + } + + // only keep the instructions that satisfy the following conditions : + // - a variable that is read must also be written in the loop + // - a variable must not be read or written more than once + // - the store instruction comes after the load instruction + std::vector candidates; + for (auto it = load_instructions.begin(); it != load_instructions.end(); ++it) { + if (!it->second) + continue; + + auto it2 = store_instructions.find(it->first); + if (it2 != store_instructions.end() && it2->second) { + llvm::DebugLoc load_loc = it->second->getDebugLoc(); + llvm::DebugLoc store_loc = it2->second->getDebugLoc(); + if (!dp_reduction_loc_exists(load_loc) || !dp_reduction_loc_exists(store_loc)) + continue; + if (load_loc.getLine() > store_loc.getLine()) + continue; + if (load_loc.getLine() == loop_info.line_nr_ || store_loc.getLine() == loop_info.line_nr_) + continue; + + if (loop_info.end_line == "LOOPENDNOTFOUND") { + errs() << "WARNING: Loop end not found! File: " << file_id << " Function: " << F.getName() + << " Start line: " << loop_info.start_line << "\n"; + continue; + } + if (loop_info.line_nr_ > std::stoul(loop_info.end_line)) + continue; + + // Check if both load and store insts belong to the loop + if (load_loc.getLine() < loop_info.line_nr_ || load_loc.getLine() > std::stoul(loop_info.end_line)) + continue; + if (store_loc.getLine() < loop_info.line_nr_ || store_loc.getLine() > std::stoul(loop_info.end_line)) + continue; + + if (it->first->hasName()) { + instr_info_t info; + info.var_name_ = dp_reduction_determineVariableName(it->second, trueVarNamesFromMetadataMap); + info.loop_line_nr_ = loop_info.line_nr_; + info.file_id_ = file_id; + info.store_inst_ = llvm::dyn_cast(it2->second); + info.load_inst_ = llvm::dyn_cast(it->second); + + candidates.push_back(info); + } + } + } + + // now check if the variables are part of a reduction operation + for (auto candidate : candidates) { + int index = isa(candidate.load_inst_) ? 1 : 0; + string varNameLoad = "LOAD"; + string varTypeLoad = "SCALAR"; + llvm::DebugLoc loc = (candidate.load_inst_)->getDebugLoc(); + + varNameLoad = dp_reduction_determineVariableName(candidate.load_inst_, trueVarNamesFromMetadataMap); + varTypeLoad = dp_reduction_determineVariableType(candidate.load_inst_); + if (llvm::isa(candidate.load_inst_->getOperand(index))) { + if (varTypeLoad.find("ARRAY,") == std::string::npos || varNameLoad.find(".addr") == std::string::npos || + varTypeLoad.find("**") != std::string::npos) { + continue; + } else if (varTypeLoad.find("ARRAY,") != std::string::npos || varNameLoad.find(".addr") != std::string::npos || + varTypeLoad.find("STRUCT,") != std::string::npos || varTypeLoad.find("**") != std::string::npos) { + llvm::Instruction *load_instr = nullptr; + llvm::Instruction *instr = dp_reduction_get_reduction_instr(candidate.store_inst_, &load_instr); + if (instr) { + candidate.load_inst_ = llvm::cast(load_instr); + candidate.operation_ = dp_reduction_get_char_for_opcode(instr); + } else { + continue; + } + } + } else { + if (varTypeLoad.find("ARRAY,") != std::string::npos || varNameLoad.find(".addr") != std::string::npos || + varTypeLoad.find("STRUCT,") != std::string::npos || varTypeLoad.find("**") != std::string::npos) { + llvm::Instruction *load_instr = nullptr; + llvm::Instruction *instr = dp_reduction_get_reduction_instr(candidate.store_inst_, &load_instr); + if (instr) { + candidate.load_inst_ = llvm::cast(load_instr); + candidate.operation_ = dp_reduction_get_char_for_opcode(instr); + } else { + // We should ignore store instructions that are not associated with a + // load e.g., pbvc[i] = c1s; + continue; + } + } else { + llvm::Instruction *load_instr = nullptr; + llvm::Instruction *instr = dp_reduction_get_reduction_instr(candidate.store_inst_, &load_instr); + if (instr) { + candidate.load_inst_ = llvm::cast(load_instr); + candidate.operation_ = dp_reduction_get_char_for_opcode(instr); + } else { + // We want to find max or min reduction operations + // We want to find the basicblock that contains the load instruction + // Then, we traverse the whole function to check if the reduction + // operation is > or < + BasicBlock *BB = (candidate.load_inst_)->getParent(); + string bbName = BB->getName().str(); + + // Ignore loops. Only look for conditional blocks + if (bbName.find("if") != std::string::npos || bbName.find("for") != std::string::npos) { + // e.g. in lulesh.cc: "if (domain.vdov(indx) != Real_t(0.)) { if ( + // dtf < dtcourant_tmp ) { dtcourant_tmp = dtf ; courant_elem = + // indx ; }}" + + // check if loaded value is used in the store instruction to prevent + // "false positives" + if (check_value_usage(candidate.store_inst_->getValueOperand(), cast(candidate.load_inst_))) { + candidate.operation_ = '>'; + } else { + continue; + } + } else { + continue; + } + } + } + } + instructions_.push_back(candidate); + } +} diff --git a/DiscoPoP/instrumentation/high_level/instrumentModule.cpp b/DiscoPoP/instrumentation/high_level/instrumentModule.cpp new file mode 100644 index 000000000..943ee12a2 --- /dev/null +++ b/DiscoPoP/instrumentation/high_level/instrumentModule.cpp @@ -0,0 +1,27 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../../DiscoPoP.hpp" + +// iterates over all functions in the module and calls 'instrument_function' +// on suitable ones +void DiscoPoP::instrument_module(llvm::Module *module, map *trueVarNamesFromMetadataMap) { + for (llvm::Module::iterator func_it = module->begin(); func_it != module->end(); ++func_it) { + llvm::Function *func = &(*func_it); + std::string fn_name = func->getName().str(); + if (func->isDeclaration() || (strcmp(fn_name.c_str(), "NULL") == 0) || fn_name.find("llvm") != std::string::npos || + inlinedFunction(func)) { + continue; + } + instrument_function(func, trueVarNamesFromMetadataMap); + } +} \ No newline at end of file diff --git a/DiscoPoP/instrumentation/low_level/insertDPFinalize.cpp b/DiscoPoP/instrumentation/low_level/insertDPFinalize.cpp new file mode 100644 index 000000000..176571b41 --- /dev/null +++ b/DiscoPoP/instrumentation/low_level/insertDPFinalize.cpp @@ -0,0 +1,20 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../../DiscoPoP.hpp" + +void DiscoPoP::insertDpFinalize(Instruction *before) { + LID lid = getLID(before, fileID); + assert((lid > 0) && "Returning on an invalid LID."); + IRBuilder<> IRB(before); + IRB.CreateCall(DpFinalize, ConstantInt::get(Int32, lid)); +} diff --git a/DiscoPoP/instrumentation/low_level/instrumentAlloca.cpp b/DiscoPoP/instrumentation/low_level/instrumentAlloca.cpp new file mode 100644 index 000000000..407160a42 --- /dev/null +++ b/DiscoPoP/instrumentation/low_level/instrumentAlloca.cpp @@ -0,0 +1,72 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../../DiscoPoP.hpp" + +// Instrumentation function inserters. +void DiscoPoP::instrumentAlloca(AllocaInst *toInstrument) { + LID lid = getLID(toInstrument, fileID); + if (lid == 0) + return; + + // NOTE: manual memory management using malloc etc. not covered yet! + + IRBuilder<> IRB(toInstrument->getNextNode()); + + vector args; + args.push_back(ConstantInt::get(Int32, lid)); + args.push_back(determineVariableName_dynamic(toInstrument)); + + bool isGlobal; + // Value *startAddr = PtrToIntInst::CreatePointerCast(toInstrument, Int64, "", + // toInstrument->getNextNonDebugInstruction()); + Value *startAddr = IRB.CreatePtrToInt(toInstrument, Int64, ""); + args.push_back(startAddr); + + Value *endAddr = startAddr; + uint64_t elementSizeInBytes = toInstrument->getAllocatedType()->getScalarSizeInBits() / 8; + Value *numElements = toInstrument->getOperand(0); + if (toInstrument->isArrayAllocation()) { + // endAddr = startAddr + allocated size + endAddr = IRB.CreateAdd(startAddr, IRB.CreateIntCast(numElements, Int64, true)); + } else if (toInstrument->getAllocatedType()->isArrayTy()) { + // unpack potentially multidimensional allocations + + Type *typeToParse = toInstrument->getAllocatedType(); + Type *elementType; + + uint64_t tmp_numElements = 1; + + // unpack multidimensional allocations + while (typeToParse->isArrayTy()) { + // extract size from current dimension and multiply to numElements + tmp_numElements *= cast(typeToParse)->getNumElements(); + // proceed one dimension + typeToParse = typeToParse->getArrayElementType(); + } + // typeToParse now contains the element type + elementType = typeToParse; + + // allocated size = Element size in Bytes * Number of elements + elementSizeInBytes = elementType->getScalarSizeInBits() / 8; + + // endAddr = startAddr + allocated size + numElements = ConstantInt::get(Int64, tmp_numElements); + endAddr = IRB.CreateAdd(startAddr, IRB.CreateIntCast(numElements, Int64, true)); + } + + args.push_back(endAddr); + args.push_back( + IRB.CreateMul(IRB.CreateIntCast(numElements, Int64, true), ConstantInt::get(Int64, elementSizeInBytes))); + args.push_back(IRB.CreateIntCast(numElements, Int64, true)); + IRB.CreateCall(DpAlloca, args, ""); +} \ No newline at end of file diff --git a/DiscoPoP/instrumentation/low_level/instrumentCalloc.cpp b/DiscoPoP/instrumentation/low_level/instrumentCalloc.cpp new file mode 100644 index 000000000..e44d8aee8 --- /dev/null +++ b/DiscoPoP/instrumentation/low_level/instrumentCalloc.cpp @@ -0,0 +1,49 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../../DiscoPoP.hpp" + +void DiscoPoP::instrumentCalloc(CallBase *toInstrument) { + // add instrumentation for calls to calloc + LID lid = getLID(toInstrument, fileID); + if (lid == 0) + return; + + // Determine correct placement for the call to __dp_new + Instruction *nextInst; + if (isa(toInstrument)) { + nextInst = toInstrument->getNextNonDebugInstruction(); + } else if (isa(toInstrument)) { + // Invoke instructions are always located at the end of a basic block. + // Invoke instructions may throw errors, in which case the successor is a + // "landing pad" basic block. If no error is thrown, the control flow is + // resumed at a "normal destination" basic block. Set the first instruction + // of the normal destination as nextInst in order to add the Instrumentation + // at the correct location. + nextInst = cast(toInstrument)->getNormalDest()->getFirstNonPHIOrDbg(); + } + + IRBuilder<> IRB(nextInst); + + vector args; + args.push_back(ConstantInt::get(Int32, lid)); + + Value *startAddr = PtrToIntInst::CreatePointerCast(toInstrument, Int64, "", nextInst); + Value *endAddr = startAddr; + Value *numBytes = IRB.CreateMul(toInstrument->getArgOperand(0), toInstrument->getArgOperand(1)); + + args.push_back(startAddr); + args.push_back(endAddr); // currently unused + args.push_back(numBytes); + + IRB.CreateCall(DpNew, args, ""); +} \ No newline at end of file diff --git a/DiscoPoP/instrumentation/low_level/instrumentDeleteOrFree.cpp b/DiscoPoP/instrumentation/low_level/instrumentDeleteOrFree.cpp new file mode 100644 index 000000000..f483f0a59 --- /dev/null +++ b/DiscoPoP/instrumentation/low_level/instrumentDeleteOrFree.cpp @@ -0,0 +1,31 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../../DiscoPoP.hpp" + +void DiscoPoP::instrumentDeleteOrFree(CallBase *toInstrument) { + // add instrumentation for delete instructions or calls to free + LID lid = getLID(toInstrument, fileID); + if (lid == 0) + return; + IRBuilder<> IRB(toInstrument->getNextNonDebugInstruction()); + + vector args; + args.push_back(ConstantInt::get(Int32, lid)); + + Value *startAddr = + PtrToIntInst::CreatePointerCast(toInstrument->getArgOperand(0), Int64, "", toInstrument->getNextNode()); + + args.push_back(startAddr); + + IRB.CreateCall(DpDelete, args, ""); +} \ No newline at end of file diff --git a/DiscoPoP/instrumentation/low_level/instrumentFuncEntry.cpp b/DiscoPoP/instrumentation/low_level/instrumentFuncEntry.cpp new file mode 100644 index 000000000..108508482 --- /dev/null +++ b/DiscoPoP/instrumentation/low_level/instrumentFuncEntry.cpp @@ -0,0 +1,103 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../../DiscoPoP.hpp" + +void DiscoPoP::instrumentFuncEntry(Function &F) { + BasicBlock &entryBB = F.getEntryBlock(); + LID lid = 0; + int32_t isStart = 0; + + StringRef fn = F.getName(); + if (fn.equals("main")) { + isStart = 1; + + // insert 'allocations' of global variables + Instruction *insertBefore = &*entryBB.begin(); + + auto tmp_end = F.getParent()->getGlobalList().end(); + tmp_end--; // necessary, since the list of Globals is modified when e.g. new + // strings are created. + for (auto Global_it = F.getParent()->getGlobalList().begin(); Global_it != tmp_end; Global_it++) { + // ignore globals which make use of "Appending Linkage", since they are + // system internal and do not behave like regular values. An example for + // such a value is @llvm.global_ctors + if (cast(&*Global_it)->hasAppendingLinkage()) { + continue; + } + + IRBuilder<> IRB(insertBefore->getNextNode()); + + vector args; + args.push_back(ConstantInt::get(Int32, lid)); + args.push_back(getOrInsertVarName_dynamic(Global_it->getName().str(), IRB)); + + bool isGlobal; + // Value *startAddr = PtrToIntInst::CreatePointerCast(toInstrument, Int64, + // "", toInstrument->getNextNonDebugInstruction()); + Value *startAddr = IRB.CreatePtrToInt(cast(&*Global_it), Int64, ""); + args.push_back(startAddr); + + Value *endAddr = startAddr; + uint64_t numElements = 1; + uint64_t allocatedSize = Global_it->getValueType()->getScalarSizeInBits(); + if (Global_it->getValueType()->isArrayTy()) { + // unpack potentially multidimensional allocations + Type *typeToParse = Global_it->getValueType(); + Type *elementType; + + // unpack multidimensional allocations + while (typeToParse->isArrayTy()) { + // extract size from current dimension and multiply to numElements + numElements *= cast(typeToParse)->getNumElements(); + // proceed one dimension + typeToParse = typeToParse->getArrayElementType(); + } + // typeToParse now contains the element type + elementType = typeToParse; + + // allocated size = Element size in Bytes * Number of elements + auto elementSizeInBytes = elementType->getScalarSizeInBits() / 8; + allocatedSize = elementSizeInBytes * numElements; + + // endAddr = startAddr + allocated size + endAddr = IRB.CreateAdd(startAddr, ConstantInt::get(Int64, allocatedSize)); + } + + args.push_back(endAddr); + args.push_back(ConstantInt::get(Int64, allocatedSize)); + args.push_back(ConstantInt::get(Int64, numElements)); + // REMOVED TO FIX INCORRECT STACK ADDRESS TRACKING + // TODO: maybe replace with explicit registration of global variables + // IRB.CreateCall(DpAlloca, args, ""); + } + } + + // We always want to insert __dp_func_entry at the beginning + // of the basic block, but we need the first valid LID to + // get the entry line of the function. + for (BasicBlock::iterator BI = entryBB.begin(), EI = entryBB.end(); BI != EI; ++BI) { + lid = getLID(&*BI, fileID); + if (lid > 0 && !isa(BI)) { + IRBuilder<> IRB(&*entryBB.begin()); + // NOTE: Changed to arrayref + ArrayRef arguments({ConstantInt::get(Int32, lid), ConstantInt::get(Int32, isStart)}); + IRB.CreateCall(DpFuncEntry, arguments); + if (DP_DEBUG) { + errs() << "DiscoPoP: funcEntry instrumented\n"; + } + break; + } + } + assert((lid > 0) && "Function entry is not instrumented because LID are all " + "invalid for the entry block."); +} \ No newline at end of file diff --git a/DiscoPoP/instrumentation/low_level/instrumentLoad.cpp b/DiscoPoP/instrumentation/low_level/instrumentLoad.cpp new file mode 100644 index 000000000..511f92d03 --- /dev/null +++ b/DiscoPoP/instrumentation/low_level/instrumentLoad.cpp @@ -0,0 +1,65 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../../DiscoPoP.hpp" + +void DiscoPoP::instrumentLoad(LoadInst *toInstrument) { + + LID lid = getLID(toInstrument, fileID); + if (lid == 0) + return; + + vector args; + + args.push_back(ConstantInt::get(Int32, lid)); + + Value *memAddr = PtrToIntInst::CreatePointerCast(toInstrument->getPointerOperand(), Int64, "", toInstrument); + args.push_back(memAddr); + + args.push_back(determineVariableName_dynamic(toInstrument)); + +#ifdef SKIP_DUP_INSTR + Twine name = Twine("L").concat(Twine(uniqueNum)); + + GlobalVariable *addrTracker = new GlobalVariable(*this->ThisModule, + Int64, // trackerType + false, GlobalVariable::PrivateLinkage, + Constant::getNullValue(Int64), // trackerType + name); + GlobalVariable *countTracker = new GlobalVariable(*this->ThisModule, Int64, false, GlobalVariable::PrivateLinkage, + Constant::getNullValue(Int64), name.concat(Twine("count"))); + uniqueNum++; + + // Load current values before instr + LoadInst *currentAddrTracker = new LoadInst::LoadInst(addrTracker, Twine(), toInstrument); + LoadInst *currentCount = new LoadInst::LoadInst(countTracker, Twine(), toInstrument); + + // add instr before before + args.push_back(currentAddrTracker); + args.push_back(currentCount); +#endif + CallInst::Create(DpRead, args, "", toInstrument); + +#ifdef SKIP_DUP_INSTR + // Post instrumentation call + // Create updates + StoreInst *addrUpdate = new StoreInst::StoreInst(memAddr, addrTracker); + BinaryOperator::BinaryOperator *incCount = + BinaryOperator::Create(Instruction::Add, currentCount, ConstantInt::get(Int64, 1)); + StoreInst *countUpdate = new StoreInst::StoreInst(incCount, countTracker); + + // add updates after before + addrUpdate->insertAfter(toInstrument); + incCount->insertAfter(toInstrument); + countUpdate->insertAfter(incCount); +#endif +} \ No newline at end of file diff --git a/DiscoPoP/instrumentation/low_level/instrumentLoopEntry.cpp b/DiscoPoP/instrumentation/low_level/instrumentLoopEntry.cpp new file mode 100644 index 000000000..d4a1ba1ec --- /dev/null +++ b/DiscoPoP/instrumentation/low_level/instrumentLoopEntry.cpp @@ -0,0 +1,42 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../../DiscoPoP.hpp" + +void DiscoPoP::instrumentLoopEntry(BasicBlock *bb, int32_t id) { + BasicBlock *currentBB = bb; + vector args; + LID lid = 0; + + // Take care of the order of instrumentation functions for loop entry + // and exit. Loop exit must appear before the next loop entry. + // Usually every loop has a .end block as the exit block, thus the + // exit of a loop will not be the entry of another loop. The first if + // check is just in case the blocks are organized in a abnormal way. + for (BasicBlock::iterator BI = currentBB->begin(), EI = currentBB->end(); BI != EI; ++BI) { + if (isa(BI)) { + Function *tmpF = (cast(BI))->getCalledFunction(); + StringRef tmpFn = tmpF->getName(); + if (tmpFn.find("__dp_loop_exit") != string::npos) + continue; + } + lid = getLID(&*BI, fileID); + if (lid > 0 && !isa(BI)) { + args.push_back(ConstantInt::get(Int32, lid)); + args.push_back(ConstantInt::get(Int32, id)); + CallInst::Create(DpLoopEntry, args, "", &*BI); + break; + } + } + // assert((lid > 0) && "Loop entry is not instrumented because LID are all + // invalid for the whole basic block."); +} \ No newline at end of file diff --git a/DiscoPoP/instrumentation/low_level/instrumentLoopExit.cpp b/DiscoPoP/instrumentation/low_level/instrumentLoopExit.cpp new file mode 100644 index 000000000..e34816b93 --- /dev/null +++ b/DiscoPoP/instrumentation/low_level/instrumentLoopExit.cpp @@ -0,0 +1,30 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../../DiscoPoP.hpp" + +void DiscoPoP::instrumentLoopExit(BasicBlock *bb, int32_t id) { + BasicBlock *currentBB = bb; + vector args; + LID lid = 0; + + for (BasicBlock::iterator BI = currentBB->begin(), EI = currentBB->end(); BI != EI; ++BI) { + lid = getLID(&*BI, fileID); + if (lid > 0 && !isa(BI)) { + args.push_back(ConstantInt::get(Int32, lid)); + args.push_back(ConstantInt::get(Int32, id)); + CallInst::Create(DpLoopExit, args, "", + &*currentBB->begin()); // always insert to the beiginning + break; + } + } +} \ No newline at end of file diff --git a/DiscoPoP/instrumentation/low_level/instrumentNewOrMalloc.cpp b/DiscoPoP/instrumentation/low_level/instrumentNewOrMalloc.cpp new file mode 100644 index 000000000..505f7e47a --- /dev/null +++ b/DiscoPoP/instrumentation/low_level/instrumentNewOrMalloc.cpp @@ -0,0 +1,49 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../../DiscoPoP.hpp" + +void DiscoPoP::instrumentNewOrMalloc(CallBase *toInstrument) { + // add instrumentation for new instructions or calls to malloc + LID lid = getLID(toInstrument, fileID); + if (lid == 0) + return; + + // Determine correct placement for the call to __dp_new + Instruction *nextInst; + if (isa(toInstrument)) { + nextInst = toInstrument->getNextNonDebugInstruction(); + } else if (isa(toInstrument)) { + // Invoke instructions are always located at the end of a basic block. + // Invoke instructions may throw errors, in which case the successor is a + // "landing pad" basic block. If no error is thrown, the control flow is + // resumed at a "normal destination" basic block. Set the first instruction + // of the normal destination as nextInst in order to add the Instrumentation + // at the correct location. + nextInst = cast(toInstrument)->getNormalDest()->getFirstNonPHIOrDbg(); + } + + IRBuilder<> IRB(nextInst); + + vector args; + args.push_back(ConstantInt::get(Int32, lid)); + + Value *startAddr = PtrToIntInst::CreatePointerCast(toInstrument, Int64, "", nextInst); + Value *endAddr = startAddr; + Value *numBytes = toInstrument->getArgOperand(0); + + args.push_back(startAddr); + args.push_back(endAddr); // currently unused + args.push_back(numBytes); + + IRB.CreateCall(DpNew, args, ""); +} \ No newline at end of file diff --git a/DiscoPoP/instrumentation/low_level/instrumentPosixMemalign.cpp b/DiscoPoP/instrumentation/low_level/instrumentPosixMemalign.cpp new file mode 100644 index 000000000..a28bbb6da --- /dev/null +++ b/DiscoPoP/instrumentation/low_level/instrumentPosixMemalign.cpp @@ -0,0 +1,49 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../../DiscoPoP.hpp" + +void DiscoPoP::instrumentPosixMemalign(CallBase *toInstrument) { + // add instrumentation for calls to posix_memalign + LID lid = getLID(toInstrument, fileID); + if (lid == 0) + return; + + // Determine correct placement for the call to __dp_new + Instruction *nextInst; + if (isa(toInstrument)) { + nextInst = toInstrument->getNextNonDebugInstruction(); + } else if (isa(toInstrument)) { + // Invoke instructions are always located at the end of a basic block. + // Invoke instructions may throw errors, in which case the successor is a + // "landing pad" basic block. If no error is thrown, the control flow is + // resumed at a "normal destination" basic block. Set the first instruction + // of the normal destination as nextInst in order to add the Instrumentation + // at the correct location. + nextInst = cast(toInstrument)->getNormalDest()->getFirstNonPHIOrDbg(); + } + + IRBuilder<> IRB(nextInst); + + vector args; + args.push_back(ConstantInt::get(Int32, lid)); + + Value *startAddr = PtrToIntInst::CreatePointerCast(toInstrument->getArgOperand(0), Int64, "", nextInst); + Value *endAddr = startAddr; + Value *numBytes = toInstrument->getArgOperand(2); + + args.push_back(startAddr); + args.push_back(endAddr); // currently unused + args.push_back(numBytes); + + IRB.CreateCall(DpNew, args, ""); +} \ No newline at end of file diff --git a/DiscoPoP/instrumentation/low_level/instrumentRealloc.cpp b/DiscoPoP/instrumentation/low_level/instrumentRealloc.cpp new file mode 100644 index 000000000..6ed72d123 --- /dev/null +++ b/DiscoPoP/instrumentation/low_level/instrumentRealloc.cpp @@ -0,0 +1,55 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../../DiscoPoP.hpp" + +void DiscoPoP::instrumentRealloc(CallBase *toInstrument) { + // add instrumentation for calls to realloc + LID lid = getLID(toInstrument, fileID); + if (lid == 0) + return; + + // Determine correct placement for the call to __dp_new + Instruction *nextInst; + if (isa(toInstrument)) { + nextInst = toInstrument->getNextNonDebugInstruction(); + } else if (isa(toInstrument)) { + // Invoke instructions are always located at the end of a basic block. + // Invoke instructions may throw errors, in which case the successor is a + // "landing pad" basic block. If no error is thrown, the control flow is + // resumed at a "normal destination" basic block. Set the first instruction + // of the normal destination as nextInst in order to add the Instrumentation + // at the correct location. + nextInst = cast(toInstrument)->getNormalDest()->getFirstNonPHIOrDbg(); + } + + IRBuilder<> IRB(nextInst); + vector args; + + // deallocate + args.push_back(ConstantInt::get(Int32, lid)); + Value *startAddr = + PtrToIntInst::CreatePointerCast(toInstrument->getArgOperand(0), Int64, "", toInstrument->getNextNode()); + args.push_back(startAddr); + IRB.CreateCall(DpDelete, args, ""); + args.clear(); + + // allocate + args.push_back(ConstantInt::get(Int32, lid)); + Value *endAddr = startAddr; + Value *numBytes = toInstrument->getArgOperand(1); + args.push_back(startAddr); + args.push_back(endAddr); // currently unused + args.push_back(numBytes); + + IRB.CreateCall(DpNew, args, ""); +} \ No newline at end of file diff --git a/DiscoPoP/instrumentation/low_level/instrumentStore.cpp b/DiscoPoP/instrumentation/low_level/instrumentStore.cpp new file mode 100644 index 000000000..daf3afe74 --- /dev/null +++ b/DiscoPoP/instrumentation/low_level/instrumentStore.cpp @@ -0,0 +1,65 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../../DiscoPoP.hpp" + +void DiscoPoP::instrumentStore(StoreInst *toInstrument) { + + LID lid = getLID(toInstrument, fileID); + if (lid == 0) + return; + + vector args; + args.push_back(ConstantInt::get(Int32, lid)); + + Value *memAddr = PtrToIntInst::CreatePointerCast(toInstrument->getPointerOperand(), Int64, "", toInstrument); + args.push_back(memAddr); + + args.push_back(determineVariableName_dynamic(toInstrument)); + +#ifdef SKIP_DUP_INSTR + Twine name = Twine("S").concat(Twine(uniqueNum)); + + GlobalVariable *addrTracker = new GlobalVariable(*this->ThisModule, + Int64, // trackerType + false, GlobalVariable::PrivateLinkage, + Constant::getNullValue(Int64), // trackerType + name); + GlobalVariable *countTracker = new GlobalVariable(*this->ThisModule, Int64, false, GlobalVariable::PrivateLinkage, + Constant::getNullValue(Int64), name.concat(Twine("count"))); + uniqueNum++; + + // Load current values before instr + LoadInst *currentAddrTracker = new LoadInst::LoadInst(addrTracker, Twine(), toInstrument); + LoadInst *currentCount = new LoadInst::LoadInst(countTracker, Twine(), toInstrument); + + // add instr before before + args.push_back(currentAddrTracker); + args.push_back(currentCount); +#endif + + CallInst::Create(DpWrite, args, "", toInstrument); + +#ifdef SKIP_DUP_INSTR + // Post instrumentation call + // Create updates + StoreInst *addrUpdate = new StoreInst::StoreInst(memAddr, addrTracker); + BinaryOperator::BinaryOperator *incCount = + BinaryOperator::Create(Instruction::Add, currentCount, ConstantInt::get(Int64, 1)); + StoreInst *countUpdate = new StoreInst::StoreInst(incCount, countTracker); + + // add updates after before + addrUpdate->insertAfter(toInstrument); + incCount->insertAfter(toInstrument); + countUpdate->insertAfter(incCount); +#endif +} \ No newline at end of file diff --git a/DiscoPoP/instrumentation/taken_branches/createInstrumentation.cpp b/DiscoPoP/instrumentation/taken_branches/createInstrumentation.cpp new file mode 100644 index 000000000..89308bcd5 --- /dev/null +++ b/DiscoPoP/instrumentation/taken_branches/createInstrumentation.cpp @@ -0,0 +1,50 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../../DiscoPoP.hpp" + +void DiscoPoP::createTakenBranchInstrumentation(Region *TopRegion, map> &BBIDToCUIDsMap) { + /* Create calls to count taken branches inbetween CUs during execution */ + for (Region::block_iterator bb = TopRegion->block_begin(); bb != TopRegion->block_end(); ++bb) { + for (BasicBlock::iterator instruction = (*bb)->begin(); instruction != (*bb)->end(); ++instruction) { + if (isa(instruction)) { + BranchInst *branchInst = cast(instruction); + // check for conditional branches, as unconditional ones can be ignored + // for counting + if (!branchInst->isUnconditional()) { + // branchInst is conditional + // prepare IRBuilder to insert instrumentation + IRBuilder<> IRB(branchInst); + // get BBId and CU IDS of the source + string source_BBID = bb->getName().str(); + for (auto source_cu : BBIDToCUIDsMap[source_BBID]) { + // get BBIds of all targets + for (int i = 0; i < branchInst->getNumSuccessors(); i++) { + string successor_BBID = branchInst->getSuccessor(i)->getName().str(); + // get CUs of all targets + for (auto target_cu : BBIDToCUIDsMap[successor_BBID]) { + // add instrumentation prior to the branch instruction + vector args; + string source_and_target = source_cu->ID + ";" + target_cu->ID; + args.push_back(getOrInsertVarName_dynamic(source_and_target, IRB)); + args.push_back(branchInst->getCondition()); + bool counter_active_on_cmp_value = (i == 0 ? 1 : 0); + args.push_back(ConstantInt::get(Int32, counter_active_on_cmp_value)); + IRB.CreateCall(DpTakenBranchCounterIncr, args); + } + } + } + } + } + } + } +} diff --git a/DiscoPoP/llvm_hooks/doFinalization.cpp b/DiscoPoP/llvm_hooks/doFinalization.cpp new file mode 100644 index 000000000..1b7fdba24 --- /dev/null +++ b/DiscoPoP/llvm_hooks/doFinalization.cpp @@ -0,0 +1,61 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../DiscoPoP.hpp" + +bool DiscoPoP::doFinalization(Module &M) { + // CUGeneration + + // write the current count of CUs to a file to avoid duplicate CUs. + outCUIDCounter = new std::ofstream(); + std::string tmp(getenv("DOT_DISCOPOP_PROFILER")); + tmp += "/DP_CUIDCounter.txt"; + outCUIDCounter->open(tmp.data(), std::ios_base::out); + if (outCUIDCounter && outCUIDCounter->is_open()) { + *outCUIDCounter << CUIDCounter; + outCUIDCounter->flush(); + outCUIDCounter->close(); + } + // CUGeneration end + + // DPInstrumentationOmission + for (Function &F : M) { + if (!F.hasName() || F.getName() != "main") + continue; + for (BasicBlock &BB : F) { + for (Instruction &I : BB) { + if (CallInst *call_inst = dyn_cast(&I)) { + if (Function *Fun = call_inst->getCalledFunction()) { + if (Fun->getName() == "__dp_finalize") { + IRBuilder<> builder(call_inst); + Value *V = builder.CreateGlobalStringPtr(StringRef(bbDepString), ".dp_bb_deps"); + CallInst::Create(F.getParent()->getOrInsertFunction("__dp_add_bb_deps", Void, CharPtr), V, "", call_inst); + } + } + } + } + } + } + // write the current count of BBs to a file to avoid duplicate BBids + outBBDepCounter = new std::ofstream(); + std::string tmp2(getenv("DOT_DISCOPOP_PROFILER")); + tmp2 += "/DP_BBDepCounter.txt"; + outBBDepCounter->open(tmp2.data(), std::ios_base::out); + if (outBBDepCounter && outBBDepCounter->is_open()) { + *outBBDepCounter << bbDepCount; + outBBDepCounter->flush(); + outBBDepCounter->close(); + } + + // DPInstrumentationOmission end + return true; +} diff --git a/DiscoPoP/llvm_hooks/doInitialization.cpp b/DiscoPoP/llvm_hooks/doInitialization.cpp new file mode 100644 index 000000000..64a648d94 --- /dev/null +++ b/DiscoPoP/llvm_hooks/doInitialization.cpp @@ -0,0 +1,121 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../DiscoPoP.hpp" + +bool DiscoPoP::doInitialization(Module &M) { + if (DP_DEBUG) { + errs() << "DiscoPoP | 190: init pass DiscoPoP \n"; + } + + // prepare environment variables + char const *tmp = getenv("DOT_DISCOPOP"); + if (tmp == NULL) { + // DOT_DISCOPOP needs to be initialized + setenv("DOT_DISCOPOP", ".discopop", 1); + } + std::string tmp_str(getenv("DOT_DISCOPOP")); + setenv("DOT_DISCOPOP_PROFILER", (tmp_str + "/profiler").data(), 1); + + // prepare .discopop directory if not present + struct stat st1 = {0}; + if (stat(getenv("DOT_DISCOPOP"), &st1) == -1) { + mkdir(getenv("DOT_DISCOPOP"), 0777); + } + // prepare profiler directory if not present + struct stat st2 = {0}; + if (stat(getenv("DOT_DISCOPOP_PROFILER"), &st2) == -1) { + mkdir(getenv("DOT_DISCOPOP_PROFILER"), 0777); + } + + // prepare target directory if not present + char const *tmp2 = getenv("DP_PROJECT_ROOT_DIR"); + if (tmp2 == NULL) { + // DP_PROJECT_ROOT_DIR needs to be initialized + std::cerr << "\nWARNING: No value for DP_PROJECT_ROOT_DIR found. \n"; + std::cerr << " As a result, library functions might be " + "instrumented which can lead to\n"; + std::cerr << " increased profiling times and unexpected behavior.\n"; + std::cerr << " Please consider to specify the environment variable " + "and rebuild.\n"; + std::cerr << " " + "https://discopop-project.github.io/discopop/setup/" + "environment_variables/\n\n"; + // define fallback + setenv("DP_PROJECT_ROOT_DIR", "/", 1); + } + + // CUGeneration + { + CUIDCounter = 0; + defaultIsGlobalVariableValue = false; + ThisModule = &M; + outCUIDCounter = NULL; + + initializeCUIDCounter(); + + for (Module::global_iterator I = ThisModule->global_begin(); I != ThisModule->global_end(); I++) { + Value *globalVariable = dyn_cast(I); + string glo = string(globalVariable->getName()); + if (glo.find(".") == glo.npos) { + programGlobalVariablesSet.insert(glo); + // originalVariablesSet.insert(glo); + } + } + } + // CUGeneration end + + // DPInstrumentation + { + // Export M to the outside + ThisModule = &M; + ThisModuleContext = &(M.getContext()); + + for (set::iterator it = GlobalVars.begin(); it != GlobalVars.end(); ++it) { + GlobalVars.erase(it); + } + + GlobalVars.clear(); + Structs.clear(); + collectDebugInfo(); + + // Initialize variables needed + setupDataTypes(); + setupCallbacks(); + + // Check loop parallelism? + if (ClCheckLoopPar) { + if (DP_DEBUG) { + errs() << "check loop parallelism \n"; + } + loopID = 0; + } else { + loopID = -1; + } + } + // DPInstrumentation end + + // DPInstrumentationOmission + { + bbDepCount = 0; + + initializeBBDepCounter(); + + ReportBB = M.getOrInsertFunction("__dp_report_bb", Void, Int32); + ReportBBPair = M.getOrInsertFunction("__dp_report_bb_pair", Void, Int32, Int32); + VNF = new dputil::VariableNameFinder(M); + int nextFreeStaticMemoryRegionID = 0; + } + // DPInstrumentationOmission end + + return true; +} diff --git a/DiscoPoP/llvm_hooks/runOnBasicBlock.cpp b/DiscoPoP/llvm_hooks/runOnBasicBlock.cpp new file mode 100644 index 000000000..e8227b45a --- /dev/null +++ b/DiscoPoP/llvm_hooks/runOnBasicBlock.cpp @@ -0,0 +1,257 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../DiscoPoP.hpp" + +/* metadata format in LLVM IR: +!5 = metadata !{ + i32, ;; Tag (see below) // DW_TAG_pointer_type: 0 + metadata, ;; Reference to context // 1 + metadata, ;; Name (may be "" for anonymous types) // 2 + metadata, ;; Reference to file where defined (may be NULL) // 3 + i32, ;; Line number where defined (may be 0) // 4 + i64, ;; Size in bits // 5 + i64, ;; Alignment in bits // 6 + i64, ;; Offset in bits // 7 + i32, ;; Flags to encode attributes, e.g. private // 8 + metadata, ;; Reference to type derived from // 9 --> get operand at +index 9 metadata, ;; (optional) Name of the Objective C property associated with + ;; Objective-C an ivar, or the type of which this + ;; pointer-to-member is pointing to members of. + metadata, ;; (optional) Name of the Objective C property getter selector. + metadata, ;; (optional) Name of the Objective C property setter selector. + i32 ;; (optional) Objective C property attributes. +} + +A real case would be: +!2 = metadata !{ + i32 524307, ;; Tag // 0 + metadata !1, ;; Context // 1 + metadata !"Color", ;; Name // 2 + metadata !1, ;; Compile unit // 3 + i32 1, ;; Line number // 4 + i64 96, ;; Size in bits // 5 + i64 32, ;; Align in bits // 6 + i64 0, ;; Offset in bits // 7 + i32 0, ;; Flags // 8 + null, ;; Derived From // 9 + metadata !3, ;; Elements // 10 --> list of elements + i32 0 ;; Runtime Language +} +*/ +// TODO: atomic variables +void DiscoPoP::runOnBasicBlock(BasicBlock &BB) { + for (BasicBlock::iterator BI = BB.begin(), E = BB.end(); BI != E; ++BI) { + if (DbgDeclareInst *DI = dyn_cast(BI)) { + assert(DI->getOperand(0)); + if (AllocaInst *alloc = dyn_cast(DI->getOperand(0))) { + Type *type = alloc->getAllocatedType(); + Type *structType = type; + unsigned depth = 0; + if (type->getTypeID() == Type::PointerTyID) { + while (structType->getTypeID() == Type::PointerTyID) { + structType = cast(structType)->getElementType(); + ++depth; + } + } + if (structType->getTypeID() == Type::StructTyID) { + assert(DI->getOperand(1)); + MDNode *varDesNode = DI->getVariable(); + assert(varDesNode->getOperand(5)); + MDNode *typeDesNode = cast(varDesNode->getOperand(5)); + MDNode *structNode = typeDesNode; + if (type->getTypeID() == Type::PointerTyID) { + MDNode *ptr = typeDesNode; + for (unsigned i = 0; i < depth; ++i) { + assert(ptr->getOperand(9)); + ptr = cast(ptr->getOperand(9)); + } + structNode = ptr; + } + DINode *strDes = cast(structNode); + // DIDescriptor strDes(structNode); + // handle the case when we have pointer to struct (or pointer to + // pointer to struct ...) + if (strDes->getTag() == dwarf::DW_TAG_pointer_type) { + DINode *ptrDes = strDes; + do { + if (structNode->getNumOperands() < 10) + break; + assert(structNode->getOperand(9)); + structNode = cast(structNode->getOperand(9)); + ptrDes = cast(structNode); + } while (ptrDes->getTag() != dwarf::DW_TAG_structure_type); + } + + if (strDes->getTag() == dwarf::DW_TAG_typedef) { + assert(strDes->getOperand(9)); + structNode = cast(strDes->getOperand(9)); + } + strDes = cast(structNode); + if (strDes->getTag() == dwarf::DW_TAG_structure_type) { + string strName(structType->getStructName().data()); + if (Structs.find(strName) == Structs.end()) { + processStructTypes(strName, structNode); + } + } + } + } + } + // alloca instruction + else if (isa(BI)) { + AllocaInst *AI = cast(BI); + + // if the option is set, check if the AllocaInst is static at the entry + // block of a function and skip it's instrumentation. This leads to a + // strong improvement of the profiling time if a lot of function calls are + // used, but results in a worse accurracy. As the default, the accurate + // profiling is used. Effectively, this check disables the instrumentation + // of allocas which belong to function parameters. + + if (DP_MEMORY_PROFILING_SKIP_FUNCTION_ARGUMENTS) { + if (!AI->isStaticAlloca()) { + // only instrument non-static alloca instructions + instrumentAlloca(AI); + } + } else { + // instrument every alloca instruction + instrumentAlloca(AI); + } + + } + // load instruction + else if (isa(BI)) { + instrumentLoad(cast(BI)); + } + // // store instruction + else if (isa(BI)) { + instrumentStore(cast(BI)); + } + // call and invoke + else if (isaCallOrInvoke(&*BI)) { + Function *F; + if (isa(BI)) + F = (cast(BI))->getCalledFunction(); + else if (isa(BI)) + F = (cast(BI))->getCalledFunction(); + + // For ordinary function calls, F has a name. + // However, sometimes the function being called + // in IR is encapsulated by "bitcast()" due to + // the way of compiling and linking. In this way, + // getCalledFunction() method returns NULL. + StringRef fn = ""; + if (F) { + fn = F->getName(); + if (fn.find("__dp_") != string::npos) // avoid instrumentation calls + { + continue; + } + if (fn.find("__clang_") != string::npos) // clang helper calls + { + continue; + } + if (fn.equals("pthread_exit")) { + // pthread_exit does not return to its caller. + // Therefore, we insert DpFuncExit before pthread_exit + IRBuilder<> IRBRet(&*BI); + ArrayRef arguments({ConstantInt::get(Int32, getLID(&*BI, fileID)), ConstantInt::get(Int32, 0)}); + IRBRet.CreateCall(DpFuncExit, arguments); + continue; + } + if (fn.equals("exit") || F->doesNotReturn()) // using exit() to terminate program + { + // only insert DpFinalize right before the main program exits + insertDpFinalize(&*BI); + continue; + } + if (fn.equals("_Znam") || fn.equals("_Znwm") || fn.equals("malloc")) { + if (isa(BI)) { + instrumentNewOrMalloc(cast(BI)); + } else if (isa(BI)) { + instrumentNewOrMalloc(cast(BI)); + } + continue; + } + if (fn.equals("realloc")) { + if (isa(BI)) { + instrumentRealloc(cast(BI)); + } else if (isa(BI)) { + instrumentRealloc(cast(BI)); + } + continue; + } + if (fn.equals("calloc")) { + if (isa(BI)) { + instrumentCalloc(cast(BI)); + } else if (isa(BI)) { + instrumentCalloc(cast(BI)); + } + } + + if (fn.equals("posix_memalign")) { + if (isa(BI)) { + instrumentPosixMemalign(cast(BI)); + } else if (isa(BI)) { + instrumentPosixMemalign(cast(BI)); + } + continue; + } + if (fn.equals("_ZdlPv") || fn.equals("free")) { + instrumentDeleteOrFree(cast(BI)); + continue; + } + } + LID lid = getLID(&*BI, fileID); + if (lid > 0) // calls on non-user code are not instrumented + { + IRBuilder<> IRBCall(&*BI); + IRBCall.CreateCall(DpCallOrInvoke, ConstantInt::get(Int32, lid)); + if (DP_DEBUG) { + if (isa(BI)) { + if (!fn.equals("")) + errs() << "calling " << fn << " on " << lid << "\n"; + else + errs() << "calling unknown function on " << lid << "\n"; + } else { + if (!fn.equals("")) + errs() << "invoking " << fn << " on " << lid << "\n"; + else + errs() << "invoking unknown function on " << lid << "\n"; + } + } + } + } + // return + else if (isa(BI)) { + LID lid = getLID(&*BI, fileID); + assert((lid > 0) && "Returning on LID = 0!"); + + Function *parent = BB.getParent(); + assert(parent != NULL); + StringRef fn = parent->getName(); + + if (fn.equals("main")) // returning from main + { + insertDpFinalize(&*BI); + } else { + IRBuilder<> IRBRet(&*BI); + ArrayRef arguments({ConstantInt::get(Int32, lid), ConstantInt::get(Int32, 0)}); + IRBRet.CreateCall(DpFuncExit, arguments); + } + + if (DP_DEBUG) { + errs() << fn << " returning on " << lid << "\n"; + } + } + } +} \ No newline at end of file diff --git a/DiscoPoP/llvm_hooks/runOnFunction.cpp b/DiscoPoP/llvm_hooks/runOnFunction.cpp new file mode 100644 index 000000000..571d47f50 --- /dev/null +++ b/DiscoPoP/llvm_hooks/runOnFunction.cpp @@ -0,0 +1,474 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../DiscoPoP.hpp" + +bool DiscoPoP::runOnFunction(Function &F) { + if (DP_DEBUG) { + errs() << "pass DiscoPoP: run pass on function " << F.getName().str() << "\n"; + } + + // avoid instrumenting functions which are defined outside the scope of the + // project + std::string dp_project_dir(getenv("DP_PROJECT_ROOT_DIR")); + SmallVector, 4> MDs; + F.getAllMetadata(MDs); + bool funcDefinedInProject = false; + for (auto &MD : MDs) { + if (MDNode *N = MD.second) { + if (auto *subProgram = dyn_cast(N)) { + std::string fullFileName = ""; + if (subProgram->getDirectory().str().length() > 0) { + fullFileName += subProgram->getDirectory().str(); + fullFileName += "/"; + } + fullFileName += subProgram->getFilename().str(); + if (fullFileName.find(dp_project_dir) != string::npos) // function defined inside project + { + funcDefinedInProject = true; + } + } + } + } + if (!funcDefinedInProject) { + return false; + } + + StringRef funcName = F.getName(); + // Avoid functions we don't want to instrument + if (funcName.find("llvm.") != string::npos) // llvm debug calls + { + return false; + } + if (funcName.find("__dp_") != string::npos) // instrumentation calls + { + return false; + } + if (funcName.find("__cx") != string::npos) // c++ init calls + { + return false; + } + if (funcName.find("__clang") != string::npos) // clang helper calls + { + return false; + } + if (funcName.find("_GLOBAL_") != string::npos) // global init calls (c++) + { + return false; + } + if (funcName.find("pthread_") != string::npos) { + return false; + } + + vector CUVector; + set globalVariablesSet; // list of variables which appear in more than + // one basic block + map> BBIDToCUIDsMap; + + determineFileID(F, fileID); + + // only instrument functions belonging to project source files + if (!fileID) + return false; + + // CUGeneration + { + /********************* Initialize root values ***************************/ + Node *root = new Node; + root->name = F.getName().str(); + root->type = nodeTypes::func; + + // Get list of arguments for this function and store them in root. + // NOTE: changed the way we get the arguments + BasicBlock *BB = &F.getEntryBlock(); + auto BI = BB->begin(); + string lid; + if (DebugLoc dl = BI->getDebugLoc()) { + lid = to_string(dl->getLine()); + } else { + lid = to_string(BI->getFunction()->getSubprogram()->getLine()); + } + + for (Function::arg_iterator it = F.arg_begin(); it != F.arg_end(); it++) { + string type_str; + raw_string_ostream rso(type_str); + (it->getType())->print(rso); + Type *variableType = it->getType(); + while (variableType->isPointerTy()) { + variableType = variableType->getPointerElementType(); + } + Variable v(it->getName().str(), rso.str(), to_string(fileID) + ":" + lid, true, true, + to_string(variableType->getScalarSizeInBits() / 8)); + root->argumentsList.push_back(v); + } + /********************* End of initialize root values + * ***************************/ + LoopInfo &LI = getAnalysis(F).getLoopInfo(); + + // get the top level region + RIpass = &getAnalysis(F); + RI = &(RIpass->getRegionInfo()); + Region *TopRegion = RI->getTopLevelRegion(); + + getTrueVarNamesFromMetadata(TopRegion, root, &trueVarNamesFromMetadataMap); + + getFunctionReturnLines(TopRegion, root); + + populateGlobalVariablesSet(TopRegion, globalVariablesSet); + + createCUs(TopRegion, globalVariablesSet, CUVector, BBIDToCUIDsMap, root, LI); + + if (DP_BRANCH_TRACKING) { + createTakenBranchInstrumentation(TopRegion, BBIDToCUIDsMap); + } + + fillCUVariables(TopRegion, globalVariablesSet, CUVector, BBIDToCUIDsMap); + + fillStartEndLineNumbers(root, LI); + + secureStream(); + + // printOriginalVariables(originalVariablesSet); + + printData(root); + + for (auto i : CUVector) { + delete (i); + } + } + // CUGeneration end + + // DPInstrumentation + { + // Check loop parallelism? + if (ClCheckLoopPar) { + LoopInfo &LI = getAnalysis(F).getLoopInfo(); + CFA(F, LI); + } + + // Instrument the entry of the function. + // Each function entry is instrumented, and the first + // executed function will initialize shadow memory. + // See the definition of __dp_func_entry() for detail. + instrumentFuncEntry(F); + + // Traverse all instructions, collect loads/stores/returns, check for calls. + for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) { + BasicBlock &BB = *FI; + runOnBasicBlock(BB); + } + + if (DP_DEBUG) { + errs() << "pass DiscoPoP: finished function\n"; + } + } + // DPInstrumentation end + + // DPInstrumentationOmission + { + if (F.getInstructionCount() == 0) + return false; + +// Enable / Disable hybrid profiling +#ifndef DP_HYBRID_PROFILING +#define DP_HYBRID_PROFILING 1 +#endif + +#if DP_HYBRID_PROFILING == 0 + return true; +#endif + ///// + + if (DP_hybrid_DEBUG) + errs() << "\n---------- Omission Analysis on " << F.getName() << " ----------\n"; + + DebugLoc dl; + Value *V; + + set omittableInstructions; + + set staticallyPredictableValues; + // Get local values (variables) + for (Instruction &I : F.getEntryBlock()) { + if (AllocaInst *AI = dyn_cast(&I)) { + staticallyPredictableValues.insert(AI); + } + } + for (BasicBlock &BB : F) { + for (Instruction &I : BB) { + // Remove from staticallyPredictableValues those which are passed to + // other functions (by ref/ptr) + if (CallInst *call_inst = dyn_cast(&I)) { + if (Function *Fun = call_inst->getCalledFunction()) { + + for (uint i = 0; i < call_inst->getNumOperands() - 1; ++i) { + V = call_inst->getArgOperand(i); + std::set::iterator it = staticallyPredictableValues.find(V); + if (it != staticallyPredictableValues.end()) { + staticallyPredictableValues.erase(V); + if (DP_hybrid_DEBUG) + errs() << VNF->getVarName(V) << "\n"; + } + } + } + } + // Remove values from locals if dereferenced + if (isa(I)) { + V = I.getOperand(0); + for (Value *w : staticallyPredictableValues) { + if (w == V) { + staticallyPredictableValues.erase(V); + } + } + } + } + } + + // assign static memory region IDs to statically predictable values and thus + // dependencies + unordered_map> staticValueNameToMemRegIDMap; // : (original variable + // name, statically assigned MemReg ID) + bool tmpIsGlobal; + long next_id; + string llvmIRVarName; + string originalVarName; + string staticMemoryRegionID; + for (auto V : staticallyPredictableValues) { + next_id = nextFreeStaticMemoryRegionID++; + llvmIRVarName = VNF->getVarName(V); + // Note: Using variables names as keys is only possible at this point, + // since the map is created for each function individually. Thus, we can + // rely on the SSA properties of LLVM IR and can assume that e.g. scoping + // is handled by LLVM and destinct variable names are introduced. + originalVarName = trueVarNamesFromMetadataMap[llvmIRVarName]; + if (originalVarName.size() == 0) { + // no original variable name could be identified using the available + // metadata. Fall back to the LLVM IR name of the value. + originalVarName = llvmIRVarName; + } + staticMemoryRegionID = "S" + to_string(next_id); + staticValueNameToMemRegIDMap[llvmIRVarName] = pair(originalVarName, staticMemoryRegionID); + } + + if (DP_hybrid_DEBUG) { + errs() << "--- Local Values ---\n"; + for (auto V : staticallyPredictableValues) { + errs() << VNF->getVarName(V) << "\n"; + } + } + + // Perform the SPA dependence analysis + int32_t fid; + determineFileID(F, fid); + map> conditionalBBDepMap; + map>> conditionalBBPairDepMap; + + auto &DT = getAnalysis(F).getDomTree(); + InstructionCFG CFG(VNF, F); + InstructionDG DG(VNF, &CFG, fid); + + for (auto edge : DG.getEdges()) { + Instruction *Src = edge->getSrc()->getItem(); + Instruction *Dst = edge->getDst()->getItem(); + + V = Src->getOperand(isa(Src) ? 1 : 0); + if (isa(Dst)) + V = dyn_cast(Dst); + + if (staticallyPredictableValues.find(V) == staticallyPredictableValues.end()) + continue; + + if (Src != Dst && DT.dominates(Dst, Src)) { + if (!conditionalBBDepMap.count(Src->getParent())) { + set tmp; + conditionalBBDepMap[Src->getParent()] = tmp; + } + conditionalBBDepMap[Src->getParent()].insert(DG.edgeToDPDep(edge, staticValueNameToMemRegIDMap)); + } else { + if (!conditionalBBPairDepMap.count(Dst->getParent())) { + map> tmp; + conditionalBBPairDepMap[Dst->getParent()] = tmp; + } + if (!conditionalBBPairDepMap[Dst->getParent()].count(Src->getParent())) { + set tmp; + conditionalBBPairDepMap[Dst->getParent()][Src->getParent()] = tmp; + } + conditionalBBPairDepMap[Dst->getParent()][Src->getParent()].insert( + DG.edgeToDPDep(edge, staticValueNameToMemRegIDMap)); + } + omittableInstructions.insert(Src); + omittableInstructions.insert(Dst); + } + + // Omit SPA instructions with no dependences + for (auto node : DG.getInstructionNodes()) { + if (!isa(node->getItem()) && !!isa(node->getItem())) + continue; + V = node->getItem()->getOperand(isa(node->getItem()) ? 1 : 0); + if (!DG.getInEdges(node).size() && !DG.getOutEdges(node).size() && + staticallyPredictableValues.find(V) != staticallyPredictableValues.end()) + omittableInstructions.insert(node->getItem()); + } + + // Add observation of execution of single basic blocks + for (auto pair : conditionalBBDepMap) { + // Insert call to reportbb + Instruction *insertionPoint = pair.first->getTerminator(); + if (isa(pair.first->getTerminator())) { + insertionPoint = insertionPoint->getPrevNonDebugInstruction(); + } + auto CI = CallInst::Create(ReportBB, ConstantInt::get(Int32, bbDepCount), "", insertionPoint); + + // ---- Insert deps into string ---- + if (bbDepCount) + bbDepString += "/"; + bool first = true; + bbDepString += to_string(bbDepCount) + "="; + for (auto dep : pair.second) { + if (!first) + bbDepString += ","; + bbDepString += dep; + first = false; + } + // --------------------------------- + ++bbDepCount; + } + + // Add observation of in-order execution of pairs of basic blocks + for (auto pair1 : conditionalBBPairDepMap) { + // Alloca and init semaphore var for BB + auto AI = new AllocaInst(Int32, 0, "__dp_bb", F.getEntryBlock().getFirstNonPHI()->getNextNonDebugInstruction()); + new StoreInst(ConstantInt::get(Int32, 0), AI, false, AI->getNextNonDebugInstruction()); + + for (auto pair2 : pair1.second) { + // Insert check for semaphore + Instruction *insertionPoint = pair2.first->getTerminator(); + if (isa(pair2.first->getTerminator())) + insertionPoint = insertionPoint->getPrevNonDebugInstruction(); + + auto LI = new LoadInst(Int32, AI, Twine(""), false, insertionPoint); + ArrayRef arguments({LI, ConstantInt::get(Int32, bbDepCount)}); + CallInst::Create(ReportBBPair, arguments, "", insertionPoint); + + // ---- Insert deps into string ---- + if (bbDepCount) + bbDepString += "/"; + bbDepString += to_string(bbDepCount); + bbDepString += "="; + bool first = true; + for (auto dep : pair2.second) { + if (!first) + bbDepString += ","; + bbDepString += dep; + first = false; + } + // ---------------------------------- + ++bbDepCount; + } + // Insert semaphore update to true + new StoreInst(ConstantInt::get(Int32, 1), AI, false, pair1.first->getTerminator()); + } + + if (DumpToDot) { + CFG.dumpToDot(fileName + "_" + string(F.getName()) + ".CFG.dot"); + DG.dumpToDot(fileName + "_" + string(F.getName()) + ".DG.dot"); + } + + if (DP_hybrid_DEBUG) { + errs() << "--- Conditional BB Dependences:\n"; + for (auto pair : conditionalBBDepMap) { + errs() << pair.first->getName() << ":\n"; + for (auto s : pair.second) { + errs() << "\t" << s << "\n"; + } + } + + errs() << "--- Conditional BB-Pair Dependences:\n"; + for (auto pair1 : conditionalBBPairDepMap) { + for (auto pair2 : pair1.second) { + errs() << pair1.first->getName() << "-"; + errs() << pair2.first->getName() << ":\n"; + for (auto s : pair2.second) + errs() << "\t" << s << "\n"; + } + } + } + + if (DP_hybrid_DEBUG) { + errs() << "--- Program Instructions:\n"; + for (BasicBlock &BB : F) { + for (Instruction &I : BB) { + if (!isa(I) && !isa(I) && !isa(I)) + continue; + errs() << "\t" << (isa(I) ? "Write " : (isa(I) ? "Alloca " : "Read ")) << " | "; + if (dl = I.getDebugLoc()) { + errs() << dl.getLine() << "," << dl.getCol(); + } else { + errs() << F.getSubprogram()->getLine() << ",*"; + } + errs() << " | "; + V = I.getOperand(isa(I) ? 1 : 0); + if (isa(I)) { + V = dyn_cast(&I); + } + errs() << VNF->getVarName(V); + + if (omittableInstructions.find(&I) != omittableInstructions.end()) { + errs() << " | OMITTED"; + } + errs() << "\n"; + } + } + } + + // Remove omittable instructions from profiling + Instruction *DP_Instrumentation; + for (Instruction *I : omittableInstructions) { + if (isa(I)) { + DP_Instrumentation = I->getNextNode()->getNextNode(); + } else { + DP_Instrumentation = I->getPrevNode(); + } + + if (!DP_Instrumentation) + continue; + if (CallInst *call_inst = dyn_cast(DP_Instrumentation)) { + if (Function *Fun = call_inst->getCalledFunction()) { + string fn = Fun->getName().str(); + if (fn == "__dp_write" || fn == "__dp_read" || fn == "__dp_alloca") { + DP_Instrumentation->eraseFromParent(); + } + } + } + } + + // Report statically identified dependencies + + staticDependencyFile = new std::ofstream(); + std::string tmp(getenv("DOT_DISCOPOP_PROFILER")); + tmp += "/static_dependencies.txt"; + staticDependencyFile->open(tmp.data(), std::ios_base::app); + + for (auto pair : conditionalBBDepMap) { + for (auto s : pair.second) { + *staticDependencyFile << s << "\n"; + } + } + staticDependencyFile->flush(); + staticDependencyFile->close(); + + if (DP_hybrid_DEBUG) + errs() << "Done with function " << F.getName() << ":\n"; + } + // DPInstrumentationOmission end + return true; +} diff --git a/DiscoPoP/llvm_hooks/runOnModule.cpp b/DiscoPoP/llvm_hooks/runOnModule.cpp new file mode 100644 index 000000000..8229918b1 --- /dev/null +++ b/DiscoPoP/llvm_hooks/runOnModule.cpp @@ -0,0 +1,69 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../DiscoPoP.hpp" + +// pass get invoked here +bool DiscoPoP::runOnModule(Module &M) { + // cout << "MODULE " << M.getName().str() << "\n"; + + long counter = 0; + // cout << "\tFUNCTION:\n"; + for (Function &F : M) { + /* + string to_be_printed = "\t(" + to_string(++counter) + " / " + + to_string(M.size()) + ") -- " + F.getName().str(); + while(to_be_printed.size() < 100){ + to_be_printed += " "; + } + cout << to_be_printed + "\r"; + */ + runOnFunction(F); + } + + // DPReduction + module_ = &M; + ctx_ = &module_->getContext(); + + reduction_file = new std::ofstream(); + std::string tmp(getenv("DOT_DISCOPOP_PROFILER")); + tmp += "/reduction.txt"; + reduction_file->open(tmp.data(), std::ios_base::app); + + loop_counter_file = new std::ofstream(); + std::string tmp2(getenv("DOT_DISCOPOP_PROFILER")); + tmp2 += "/loop_counter_output.txt"; + loop_counter_file->open(tmp2.data(), std::ios_base::app); + + /* + bool success = dp_reduction_init_util(FileMappingPath); + if (!success) { + llvm::errs() << "could not find the FileMapping file: " << FileMappingPath + << "\n"; return false; + } + */ + instrument_module(&M, &trueVarNamesFromMetadataMap); + + dp_reduction_insert_functions(); + + if (reduction_file != NULL && reduction_file->is_open()) { + reduction_file->flush(); + reduction_file->close(); + } + + if (loop_counter_file != NULL && loop_counter_file->is_open()) { + loop_counter_file->flush(); + loop_counter_file->close(); + } + // End DPReduction + return true; +} diff --git a/DiscoPoP/static_analysis/createCUs.cpp b/DiscoPoP/static_analysis/createCUs.cpp new file mode 100644 index 000000000..43bbe981b --- /dev/null +++ b/DiscoPoP/static_analysis/createCUs.cpp @@ -0,0 +1,344 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../DiscoPoP.hpp" + +void DiscoPoP::createCUs(Region *TopRegion, set &globalVariablesSet, vector &CUVector, + map> &BBIDToCUIDsMap, Node *root, LoopInfo &LI) { + const DataLayout *DL = &ThisModule->getDataLayout(); // used to get data size of variables, + // pointers, structs etc. + Node *currentNode = root; + CU *cu; + int lid; + string varName; + bool isGlobalVar = false; + string varType; + set suspiciousVariables; + string basicBlockName; + + map loopToNodeMap; + + for (Region::block_iterator bb = TopRegion->block_begin(); bb != TopRegion->block_end(); ++bb) { + + // Get the closest loop where bb lives in. + // (loop == NULL) if bb is not in any loop. + Loop *loop = LI.getLoopFor(*bb); + if (loop) { + // if bb is in a loop and if we have already created a node for that loop, + // assign it to currentNode. + if (loopToNodeMap.find(loop) != loopToNodeMap.end()) { + currentNode = loopToNodeMap[loop]; + } + // else, create a new Node for the loop, add it as children of currentNode + // and add it to the map. + else { + Node *n = new Node; + n->type = nodeTypes::loop; + n->parentNode = currentNode; + currentNode->childrenNodes.push_back(n); + + loopToNodeMap[loop] = n; + currentNode = n; + } + } else { + // end of loops. go to the parent of the loop. may have to jump several + // nodes in case of nested loops + for (map::iterator it = loopToNodeMap.begin(); it != loopToNodeMap.end(); it++) + if (it->second == currentNode) // current node found in loop map jump to its parent. + { + currentNode = currentNode->parentNode; + it = loopToNodeMap.begin(); // search the whole map again for current node + if (it->second == currentNode) // due to it++ we need to check first + // element of map ourself + currentNode = currentNode->parentNode; + } + } + + cu = new CU; + + if (bb->getName().size() == 0) + bb->setName(cu->ID); + + cu->BBID = bb->getName().str(); + cu->BB = *bb; + currentNode->childrenNodes.push_back(cu); + vector basicBlockCUVector; + basicBlockCUVector.push_back(cu); + BBIDToCUIDsMap.insert(pair>(bb->getName(), basicBlockCUVector)); + DILocalScope *scopeBuffer = NULL; + + for (BasicBlock::iterator instruction = (*bb)->begin(); instruction != (*bb)->end(); ++instruction) { + // NOTE: 'instruction' --> '&*instruction' + lid = getLID(&*instruction, fileID); + basicBlockName = bb->getName().str(); + + // Do not allow to combine Instructions from different scopes in the + // source code. + if ((&*instruction)->getDebugLoc()) { + if ((&*instruction)->getDebugLoc()->getScope() != scopeBuffer) { + // scopes are not equal + + int scopeIsParentOfBuffer = 0; + if (scopeBuffer) { + scopeIsParentOfBuffer = (&*instruction)->getDebugLoc()->getScope() == scopeBuffer->getScope(); + } + + if (scopeIsParentOfBuffer) { + // allow a combination of two CU's if the second scope is the parent + // of the first scope + } else { + // create a new CU. Do not allow to combine Instructions from + // different scopes in the source code. + + // create new CU if the old one contains any instruction + if ((!cu->readPhaseLineNumbers.empty()) || (!cu->writePhaseLineNumbers.empty()) || + (!cu->returnInstructions.empty())) { + cu->startLine = *(cu->instructionsLineNumbers.begin()); + cu->endLine = *(cu->instructionsLineNumbers.rbegin()); + + cu->basicBlockName = basicBlockName; + CUVector.push_back(cu); + suspiciousVariables.clear(); + CU *temp = cu; // keep current CU to make a reference to the successor CU + cu = new CU; + + cu->BBID = bb->getName().str(); + cu->BB = *bb; + + currentNode->childrenNodes.push_back(cu); + temp->successorCUs.push_back(cu->ID); + BBIDToCUIDsMap[bb->getName().str()].push_back(cu); + } + } + // update scopeBuffer + scopeBuffer = (&*instruction)->getDebugLoc()->getScope(); + } + } + + if (lid > 0) { + cu->instructionsLineNumbers.insert(lid); + cu->instructionsCount++; + // find return instructions + if (isa(instruction)) { + cu->returnInstructions.insert(lid); + } + // find branches to return instructions, i.e. return statements + else if (isa(instruction)) { + if ((cast(instruction))->isUnconditional()) { + if ((cast(instruction))->getNumSuccessors() == 1) { + BasicBlock *successorBB = (cast(instruction))->getSuccessor(0); + for (BasicBlock::iterator innerInstruction = successorBB->begin(); innerInstruction != successorBB->end(); + ++innerInstruction) { + if (isa(innerInstruction)) { + cu->returnInstructions.insert(lid); + break; + } + } + } + } + } + if (isa(instruction)) { + // get size of data written into memory by this store instruction + Value *operand = instruction->getOperand(1); + Type *Ty = operand->getType(); + unsigned u = DL->getTypeSizeInBits(Ty); + cu->writeDataSize += u; + varName = determineVariableName_static(&*instruction, isGlobalVar, false); + varType = determineVariableType(&*instruction); + suspiciousVariables.insert(varName); + if (lid > 0) + cu->writePhaseLineNumbers.insert(lid); + } else if (isa(instruction)) { + // get size of data read from memory by this load instruction + Type *Ty = instruction->getType(); + unsigned u = DL->getTypeSizeInBits(Ty); + cu->readDataSize += u; + varName = determineVariableName_static(&*instruction, isGlobalVar, false); + if (suspiciousVariables.count(varName)) { + // VIOLATION OF CAUTIOUS PROPERTY + // it is a load instruction which read the value of a global + // variable. + // This global variable has already been stored previously. + // A new CU should be created here. + cu->readPhaseLineNumbers.erase(lid); + cu->writePhaseLineNumbers.erase(lid); + cu->instructionsLineNumbers.erase(lid); + cu->instructionsCount--; + if (cu->instructionsLineNumbers.empty()) { + // cu->removeCU(); + cu->startLine = -1; + cu->endLine = -1; + } else { + cu->startLine = *(cu->instructionsLineNumbers.begin()); + cu->endLine = *(cu->instructionsLineNumbers.rbegin()); + } + cu->basicBlockName = basicBlockName; + CUVector.push_back(cu); + suspiciousVariables.clear(); + CU *temp = cu; // keep current CU to make a reference to the successor CU + cu = new CU; + + cu->BBID = bb->getName().str(); + cu->BB = *bb; + + currentNode->childrenNodes.push_back(cu); + temp->successorCUs.push_back(cu->ID); + BBIDToCUIDsMap[bb->getName().str()].push_back(cu); + if (lid > 0) { + cu->readPhaseLineNumbers.insert(lid); + cu->instructionsLineNumbers.insert(lid); + } + } else { + if (globalVariablesSet.count(varName) || programGlobalVariablesSet.count(varName)) { + if (lid > 0) + cu->readPhaseLineNumbers.insert(lid); + } + } + } else if (isa(instruction)) { + // get the name of the called function and check if a FileIO function + // is called + CallInst *ci = cast(instruction); + set IOFunctions{ + "fopen", "fopen_s", "freopen", "freopen_s", "fclose", "fflush", "setbuf", + "setvbuf", "fwide", "fread", "fwrite", "fgetc", "getc", "fgets", + "fputc", "putc", "fputs", "getchar", "gets", "gets_s", "putchar", + "puts", "ungetc", "fgetwc", "getwc", "fgetws", "fputwc", "putwc", + "fputws", "getwchar", "putwchar", "ungetwc", "scanf", "fscanf", "sscanf", + "scanf_s", "fscanf_s", "sscanf_s", "vscanf", "vfscanf", "vsscanf", "vscanf_s", + "vfscanf_s", "vsscanf_s", "printf", "fprintf", "sprintf", "snprintf", "printf_s", + "fprintf_s", "sprintf_s", "snprintf_s", "vprintf", "vfprintf", "vsprintf", "vsnprintf", + "vprintf_s", "vfprintf_s", "vsprintf_s", "vsnprintf_s", "wscanf", "fwscanf", "swscanf", + "wscanf_s", "fwscanf_s", "swscanf_s", "vwscanf", "vfwscanf", "vswscanf", "vwscanf_s", + "vfwscanf_s", "vswscanf_s", "wprintf", "fwprintf", "swprintf", "wprintf_s", "wprintf_s", + "swprintf_s", "snwprintf_s", "vwprintf", "vfwprintf", "vswprintf", "vwprintf_s", "vfwprintf_s", + "vswprintf_s", "vsnwprintf_s", "ftell", "fgetpos", "fseek", "fsetpos", "rewind", + "clearerr", "feof", "ferror", "perror", "remove", "rename", "tmpfile", + "tmpfile_s", "tmpnam", "tmpnam_s", "__isoc99_fscanf"}; + if (ci) { + if (ci->getCalledFunction()) { + if (ci->getCalledFunction()->hasName()) { + if (find(IOFunctions.begin(), IOFunctions.end(), ci->getCalledFunction()->getName().str()) != + IOFunctions.end()) { + // Called function performs FileIO + cu->performsFileIO = true; + } + } + } + } + } + } + } + if (cu->instructionsLineNumbers.empty()) { + // cu->removeCU(); + cu->startLine = -1; + cu->endLine = -1; + } else { + cu->startLine = *(cu->instructionsLineNumbers.begin()); + cu->endLine = *(cu->instructionsLineNumbers.rbegin()); + } + + cu->basicBlockName = basicBlockName; + CUVector.push_back(cu); + suspiciousVariables.clear(); + + // check for call instructions in current basic block + for (BasicBlock::iterator instruction = (*bb)->begin(); instruction != (*bb)->end(); ++instruction) { + // Note: Don't create nodes for library functions (c++/llvm). + LID lid = getLID(&*instruction, fileID); + if (lid > 0) { + if (isa(instruction)) { + CallInst *ci = cast(instruction); + Function *f = ci->getCalledFunction(); + // TODO: DO the same for Invoke inst + + string lid; + if (f) { + Function::iterator FI = f->begin(); + bool externalFunction = true; + for (Function::iterator FI = f->begin(), FE = f->end(); FI != FE; ++FI) { + externalFunction = false; + auto tempBI = FI->begin(); + if (DebugLoc dl = tempBI->getDebugLoc()) { + lid = to_string(dl->getLine()); + } else { + if (tempBI->getFunction()->getSubprogram()) + lid = to_string(tempBI->getFunction()->getSubprogram()->getLine()); + else { + lid = "LineNotFound"; + } + } + break; + } + if (externalFunction) + continue; + } else { + lid = "LineNotFound"; + } + + Node *n = new Node; + n->type = nodeTypes::dummy; + // For ordinary function calls, F has a name. + // However, sometimes the function being called + // in IR is encapsulated by "bitcast()" due to + // the way of compiling and linking. In this way, + // getCalledFunction() method returns NULL. + // Also, getName() returns NULL if this is an indirect function call. + if (f) { + n->name = f->getName().str(); + + // @Zia: This for loop appeared after the else part. For some + // function calls, the value of f is null. I guess that is why you + // have checked if f is not null here. Anyway, I (Mohammad) had to + // bring the for loop inside to avoid the segmentation fault. If you + // think it is not appropriate, find a solution for it. 14.2.2016 + for (Function::arg_iterator it = f->arg_begin(); it != f->arg_end(); it++) { + string type_str; + raw_string_ostream rso(type_str); + (it->getType())->print(rso); + Type *variableType = it->getType(); + while (variableType->isPointerTy()) { + variableType = variableType->getPointerElementType(); + } + Variable v(string(it->getName()), rso.str(), lid, true, true, + to_string(variableType->getScalarSizeInBits() / 8)); + n->argumentsList.push_back(v); + } + } else // get name of the indirect function which is called + { + Value *v = (cast(instruction))->getCalledOperand(); + Value *sv = v->stripPointerCasts(); + n->name = sv->getName().str(); + } + + // Recursive functions + CallGraphWrapperPass *CGWP = &(getAnalysis()); + if (isRecursive(*f, CGWP->getCallGraph())) { + int lid = getLID(&*instruction, fileID); + n->recursiveFunctionCall = n->name + " " + dputil::decodeLID(lid) + ","; + } + + vector BBCUsVector = BBIDToCUIDsMap[bb->getName().str()]; + // locate the CU where this function call belongs + for (auto i : BBCUsVector) { + int lid = getLID(&*instruction, fileID); + if (lid >= i->startLine && lid <= i->endLine) { + i->instructionsLineNumbers.insert(lid); + i->childrenNodes.push_back(n); + i->callLineTofunctionMap[lid].push_back(n); + break; + } + } + } + } + } + } +} diff --git a/DiscoPoP/static_analysis/fillCUVariables.cpp b/DiscoPoP/static_analysis/fillCUVariables.cpp new file mode 100644 index 000000000..3afa00781 --- /dev/null +++ b/DiscoPoP/static_analysis/fillCUVariables.cpp @@ -0,0 +1,73 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../DiscoPoP.hpp" + +void DiscoPoP::fillCUVariables(Region *TopRegion, set &globalVariablesSet, vector &CUVector, + map> &BBIDToCUIDsMap) { + int lid; + string varName, varType, varDefLine; + bool isGlobalVar = false; + // Changed TerminatorInst to Instuction + const Instruction *TInst; + string successorBB; + + for (Region::block_iterator bb = TopRegion->block_begin(); bb != TopRegion->block_end(); ++bb) { + CU *lastCU = BBIDToCUIDsMap[bb->getName().str()].back(); // get the last CU in the basic block + // get all successor basic blocks for bb + TInst = bb->getTerminator(); + for (unsigned i = 0, nSucc = TInst->getNumSuccessors(); i < nSucc; ++i) { + // get the name of successor basicBlock + successorBB = TInst->getSuccessor(i)->getName().str(); + // get the first CU of the successor basicBlock and record its ID in + // current CU's successorCUs + lastCU->successorCUs.push_back(BBIDToCUIDsMap[successorBB].front()->ID); + } + + auto bbCU = BBIDToCUIDsMap[bb->getName().str()].begin(); + for (BasicBlock::iterator instruction = (*bb)->begin(); instruction != (*bb)->end(); ++instruction) { + if (isa(instruction) || isa(instruction)) { + // NOTE: changed 'instruction' to '&*instruction' + lid = getLID(&*instruction, fileID); + if (lid == 0) + continue; + // NOTE: changed 'instruction' to '&*instruction', next 2 lines + varName = determineVariableName_static(&*instruction, isGlobalVar, false); + varType = determineVariableType(&*instruction); + + int index = isa(&*instruction) ? 1 : 0; + Type *variableType = (&*instruction)->getOperand(index)->getType(); + while (variableType->isPointerTy()) { + variableType = variableType->getPointerElementType(); + } + + string varSizeInBytes = to_string(variableType->getScalarSizeInBits() / 8); + + varDefLine = determineVariableDefLine(&*instruction); + + bool readAccess = isa(instruction); + bool writeAccess = isa(instruction); + + Variable v(varName, varType, varDefLine, readAccess, writeAccess, varSizeInBytes); + + if (lid > (*bbCU)->endLine) { + bbCU = next(bbCU, 1); + } + if (globalVariablesSet.count(varName) || programGlobalVariablesSet.count(varName)) { + (*bbCU)->globalVariableNames.insert(v); + } else { + (*bbCU)->localVariableNames.insert(v); + } + } + } + } +} diff --git a/DiscoPoP/static_analysis/populateGlobalVariablesSet.cpp b/DiscoPoP/static_analysis/populateGlobalVariablesSet.cpp new file mode 100644 index 000000000..9af29c78e --- /dev/null +++ b/DiscoPoP/static_analysis/populateGlobalVariablesSet.cpp @@ -0,0 +1,47 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../DiscoPoP.hpp" + +// recieves the region and outputs all variables and variables crossing basic +// block boundaries in the region. +void DiscoPoP::populateGlobalVariablesSet(Region *TopRegion, set &globalVariablesSet) { + + map variableToBBMap; + bool isGlobalVariable; + for (Region::block_iterator bb = TopRegion->block_begin(); bb != TopRegion->block_end(); ++bb) { + for (BasicBlock::iterator instruction = (*bb)->begin(); instruction != (*bb)->end(); ++instruction) { + if (isa(instruction) || isa(instruction) || isa(instruction)) { + + // NOTE: changed 'instruction' to '&*instruction' + string varName = determineVariableName_static(&*instruction, isGlobalVariable, false); + + if (isGlobalVariable) // add it if it is a global variable in the + // program + { + programGlobalVariablesSet.insert(varName); + } + + if (variableToBBMap.find(varName) != variableToBBMap.end()) { + // this var has already once recordded. check for bb id + if (variableToBBMap[varName] != *bb) { + // global variable found. Insert into the globalVariablesSet + globalVariablesSet.insert(varName); + } + } else { + // record usage of the variable. + variableToBBMap.insert(pair(varName, *bb)); + } + } + } + } +} \ No newline at end of file diff --git a/DiscoPoP/utils/CFA.cpp b/DiscoPoP/utils/CFA.cpp new file mode 100644 index 000000000..058a54054 --- /dev/null +++ b/DiscoPoP/utils/CFA.cpp @@ -0,0 +1,118 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../DiscoPoP.hpp" + +// Control-flow analysis functions + +void DiscoPoP::CFA(Function &F, LoopInfo &LI) { + SmallVector ExitBlocks; + for (Function::iterator BB = F.begin(), BE = F.end(); BB != BE; ++BB) { + BasicBlock *tmpBB = &*BB; + ExitBlocks.clear(); + + // Get the closest loop where tmpBB lives in. + // (L == NULL) if tmpBB is not in any loop. + Loop *L = LI.getLoopFor(tmpBB); + + // Check if tmpBB is the loop header (.cond) block. + if (L != NULL && LI.isLoopHeader(tmpBB)) { + StringRef loopType = tmpBB->getName().split('.').first; + if (DP_DEBUG) { + errs() << "loop [" << loopType << "] header: " << tmpBB->getName() << "\n"; + } + + // If tmpBB is the header block, get the exit blocks of the loop. + if (L->hasDedicatedExits()) { + // loop exits are in canonical form + L->getUniqueExitBlocks(ExitBlocks); + } else { + // loop exits are NOT in canonical form + L->getExitBlocks(ExitBlocks); + } + + if (ExitBlocks.size() == 0) { + errs() << "WARNING: loop at " << tmpBB << " is ignored: exit BB not found.\n"; + continue; + } + + // When loop has break statement inside, exit blocks may contain + // the if-else block containing the break. Since we always want + // to find the real exit (.end) block, we need to check the + // successors of the break statement(s). + SmallVector RealExitBlocks; + if (DP_DEBUG) { + errs() << "loop exits:"; + } + for (SmallVectorImpl::iterator EI = ExitBlocks.begin(), END = ExitBlocks.end(); EI != END; ++EI) { + StringRef exitType = (*EI)->getName().split('.').first; + if (exitType.equals(loopType) && ((*EI)->getName().find("end") != string::npos) && + (std::find(RealExitBlocks.begin(), RealExitBlocks.end(), *EI) == RealExitBlocks.end())) { + RealExitBlocks.push_back(*EI); + if (DP_DEBUG) { + errs() << " " << (*EI)->getName(); + } + } else { + // Changed TerminatorInst to Instruction + Instruction *TI = (*EI)->getTerminator(); + assert(TI != NULL && "Exit block is not well formed!"); + unsigned int numSucc = TI->getNumSuccessors(); + for (unsigned int i = 0; i < numSucc; ++i) { + BasicBlock *succ = TI->getSuccessor(i); + exitType = succ->getName().split('.').first; + if (exitType.equals(loopType) && (succ->getName().find("end") != string::npos) && + (std::find(RealExitBlocks.begin(), RealExitBlocks.end(), succ) == RealExitBlocks.end())) { + RealExitBlocks.push_back(succ); + if (DP_DEBUG) { + errs() << " " << succ->getName(); + } + } + } + } + } + if (DP_DEBUG) { + errs() << "\n"; + } + + // assert((RealExitBlocks.size() == 1) && "Loop has more than one real + // exit block!"); + if (RealExitBlocks.size() == 0) { + if (DP_VERBOSE) { + errs() << "WARNING: loop at " << tmpBB << " is ignored: exit blocks are not well formed.\n"; + } + continue; + } + + // Check if entry block and exit block(s) have valid LID. + bool hasValidEntry = sanityCheck(tmpBB); + bool hasValidExit = false; + for (SmallVectorImpl::iterator EI = RealExitBlocks.begin(), END = RealExitBlocks.end(); EI != END; + ++EI) { + hasValidExit = sanityCheck(*EI); + if (hasValidExit == true) + break; + } + + if (hasValidEntry && hasValidExit) { + // Instrument loop header block. + instrumentLoopEntry(tmpBB, loopID); + + // Instrument loop exit block(s). + for (SmallVectorImpl::iterator EI = RealExitBlocks.begin(), END = RealExitBlocks.end(); EI != END; + ++EI) { + instrumentLoopExit(*EI, loopID); + } + ++loopID; + } + } + } +} diff --git a/DiscoPoP/utils/output.cpp b/DiscoPoP/utils/output.cpp new file mode 100644 index 000000000..681553fb4 --- /dev/null +++ b/DiscoPoP/utils/output.cpp @@ -0,0 +1,213 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../DiscoPoP.hpp" + +/********** Output functions *********/ +string DiscoPoP::xmlEscape(string data) { + string::size_type pos = 0; + for (;;) { + pos = data.find_first_of("\"&<>", pos); + if (pos == string::npos) + break; + string replacement; + switch (data[pos]) { + case '\"': + replacement = """; + break; + case '&': + replacement = "&"; + break; + case '<': + replacement = "<"; + break; + case '>': + replacement = ">"; + break; + default:; + } + data.replace(pos, 1, replacement); + pos += replacement.size(); + }; + return data; +} + +void DiscoPoP::secureStream() { + outOriginalVariables = new std::ofstream(); + std::string tmp(getenv("DOT_DISCOPOP_PROFILER")); + tmp += "/OriginalVariables.txt"; + outOriginalVariables->open(tmp.data(), std::ios_base::app); + + outCUs = new std::ofstream(); + std::string tmp2(getenv("DOT_DISCOPOP_PROFILER")); + tmp2 += "/Data.xml"; + outCUs->open(tmp2.data(), std::ios_base::app); +} + +string DiscoPoP::getLineNumbersString(set LineNumbers) { + string line = ""; + for (auto li : LineNumbers) { + std::string temp = ',' + dputil::decodeLID(li); + if (temp != ",*") { + if (line == "") { + line = dputil::decodeLID(li); + } else { + line = line + temp; + } + } + } + return line; +} + +string DiscoPoP::getChildrenNodesString(Node *root) { + string childrenIDs = ""; + int i = 0; + std::for_each(root->childrenNodes.begin(), root->childrenNodes.end(), [&](Node *node) { + if (i == 0) { + childrenIDs = node->ID; + i++; + } else { + childrenIDs += "," + node->ID; + } + }); + return childrenIDs; +} + +void DiscoPoP::printData(Node *root) { + *outCUs << "" << endl << endl; + + printTree(root, true); + + *outCUs << "" << endl << endl << endl; + + closeOutputFiles(); +} + +void DiscoPoP::printTree(Node *root, bool isRoot) { + printNode(root, isRoot); + + std::for_each(root->childrenNodes.begin(), root->childrenNodes.end(), [&](Node *node) { + if (node->type == nodeTypes::func) { + isRoot = false; + } + printTree(node, isRoot); + }); +} + +void DiscoPoP::printNode(Node *root, bool isRoot) { + if (root->name.find("llvm")) { + string start = ""; + if (root->type == nodeTypes::loop) { + start = loopStartLines[root->ID]; + } else { + start = dputil::decodeLID(root->startLine); + } + *outCUs << "\tID) << "\"" + << " type=\"" << root->type << "\"" + << " name=\"" << xmlEscape(root->name) << "\"" + << " startsAtLine = \"" << start << "\"" + << " endsAtLine = \"" << dputil::decodeLID(root->endLine) << "\"" + << ">" << endl; + *outCUs << "\t\t" << getChildrenNodesString(root) << "" << endl; + if (root->type == nodeTypes::func || root->type == nodeTypes::dummy) { + *outCUs << "\t\t" << endl; + for (auto ai : root->argumentsList) { + *outCUs << "\t\t\t" + << xmlEscape(ai.name) << "" << endl; + } + *outCUs << "\t\t" << endl; + + string rlVals = ""; + for (auto rl : root->returnLines) { + rlVals += dputil::decodeLID(rl) + ", "; + } + *outCUs << "\t\t" << rlVals << "" << endl; + } + + if (root->type == nodeTypes::cu) { + CU *cu = static_cast(root); + *outCUs << "\t\t" << cu->BBID << "" << endl; + *outCUs << "\t\t" << cu->readDataSize << "" << endl; + *outCUs << "\t\t" << cu->writeDataSize << "" << endl; + *outCUs << "\t\t" << cu->performsFileIO << "" << endl; + + *outCUs << "\t\t" << cu->instructionsCount << "" << endl; + *outCUs << "\t\tinstructionsLineNumbers).size() << "\">" + << getLineNumbersString(cu->instructionsLineNumbers) << "" << endl; + *outCUs << "\t\treadPhaseLineNumbers).size() << "\">" + << getLineNumbersString(cu->readPhaseLineNumbers) << "" << endl; + *outCUs << "\t\twritePhaseLineNumbers).size() << "\">" + << getLineNumbersString(cu->writePhaseLineNumbers) << "" << endl; + *outCUs << "\t\treturnInstructions).size() << "\">" + << getLineNumbersString(cu->returnInstructions) << "" << endl; + *outCUs << "\t\t" << endl; + for (auto sucCUi : cu->successorCUs) { + *outCUs << "\t\t\t" << sucCUi << "" << endl; + } + *outCUs << "\t\t" << endl; + + *outCUs << "\t\t" << endl; + for (auto lvi : cu->localVariableNames) { + *outCUs << "\t\t\t" + << xmlEscape(lvi.name) << "" << endl; + } + *outCUs << "\t\t" << endl; + + *outCUs << "\t\t" << endl; + for (auto gvi : cu->globalVariableNames) { + *outCUs << "\t\t\t" + << xmlEscape(gvi.name) << "" << endl; + } + *outCUs << "\t\t" << endl; + + *outCUs << "\t\t" << endl; + for (auto i : (cu->callLineTofunctionMap)) { + for (auto ii : i.second) { + *outCUs << "\t\t\t" << ii->ID << "" + << endl; + // specifica for recursive fucntions inside loops. (Mo 5.11.2019) + *outCUs << "\t\t\t\t" << ii->recursiveFunctionCall << "" + << endl; + } + } + *outCUs << "\t\t" << endl; + } + + *outCUs << "\t" << endl << endl; + } +} + +void DiscoPoP::closeOutputFiles() { + + if (outCUs != NULL && outCUs->is_open()) { + outCUs->flush(); + outCUs->close(); + } + + if (outOriginalVariables != NULL && outOriginalVariables->is_open()) { + outOriginalVariables->flush(); + outOriginalVariables->close(); + } + + // delete outCUs; +} +/************** End of output functions *******************/ \ No newline at end of file diff --git a/DiscoPoP/utils/simple.cpp b/DiscoPoP/utils/simple.cpp new file mode 100644 index 000000000..e93e0cf55 --- /dev/null +++ b/DiscoPoP/utils/simple.cpp @@ -0,0 +1,184 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../DiscoPoP.hpp" + +Type *DiscoPoP::pointsToStruct(PointerType *PTy) { + assert(PTy); + Type *structType = PTy; + if (PTy->getTypeID() == Type::PointerTyID) { + while (structType->getTypeID() == Type::PointerTyID) { + structType = cast(structType)->getElementType(); + } + } + return structType->getTypeID() == Type::StructTyID ? structType : NULL; +} + +Value *DiscoPoP::findStructMemberName(MDNode *structNode, unsigned idx, IRBuilder<> &builder) { + assert(structNode); + assert(structNode->getOperand(10)); + MDNode *memberListNodes = cast(structNode->getOperand(10)); + if (idx < memberListNodes->getNumOperands()) { + assert(memberListNodes->getOperand(idx)); + MDNode *member = cast(memberListNodes->getOperand(idx)); + if (member->getOperand(3)) { + return getOrInsertVarName_dynamic(dyn_cast(member->getOperand(3))->getString().str(), builder); + } + } + return NULL; +} + +DIGlobalVariable *DiscoPoP::findDbgGlobalDeclare(GlobalVariable *v) { + assert(v && "Global variable cannot be null"); + for (set::iterator it = GlobalVars.begin(); it != GlobalVars.end(); ++it) { + if ((*it)->getDisplayName() == v->getName()) + return *it; + } + return NULL; +} + +void DiscoPoP::collectDebugInfo() { + if (NamedMDNode *CU_Nodes = ThisModule->getNamedMetadata("llvm.dbg.cu")) { + for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { + DICompileUnit *CU = cast(CU_Nodes->getOperand(i)); + auto GVs = CU->getGlobalVariables(); + for (unsigned i = 0, e = GVs.size(); i < e; ++i) { + DIGlobalVariable *DIG = GVs[i]->getVariable(); + if (DIG) { + GlobalVars.insert(DIG); + } + } + } + } +} + +bool DiscoPoP::isaCallOrInvoke(Instruction *BI) { + return (BI != NULL) && ((isa(BI) && (!isa(BI))) || isa(BI)); +} + +bool DiscoPoP::sanityCheck(BasicBlock *BB) { + LID lid; + for (BasicBlock::iterator BI = BB->begin(), EI = BB->end(); BI != EI; ++BI) { + lid = getLID(&*BI, fileID); + if (lid > 0) { + return true; + } + } + if (DP_VERBOSE) { + errs() << "WARNING: basic block " << BB << " doesn't contain valid LID.\n"; + } + return false; +} + +bool DiscoPoP::check_value_usage(llvm::Value *parentValue, llvm::Value *searchedValue) { + // Return true, if searchedValue is used within the computation of parentValue + if (parentValue == searchedValue) { + return true; + } + + // check operands recursively, if parentValue is not a constant yet + if (isa(parentValue)) { + return false; + } + // if parentValue is not an Instruction, the value can not be used, thus + // return false + if (!isa(parentValue)) { + errs() << "parentValue not an Instruction.\n"; + return false; + } + + llvm::Instruction *parentInstruction = cast(parentValue); + for (int idx = 0; idx < parentInstruction->getNumOperands(); idx++) { + if (check_value_usage(parentInstruction->getOperand(idx), searchedValue)) { + return true; + } + } + + return false; +} + +bool DiscoPoP::inlinedFunction(Function *F) { + for (Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) { + for (BasicBlock::iterator BI = FI->begin(), E = FI->end(); BI != E; ++BI) { + if (DbgDeclareInst *DI = dyn_cast(BI)) { + if (DI->getDebugLoc()->getInlinedAt()) + return true; + } + } + } + return false; +} + +bool DiscoPoP::isRecursive(Function &F, CallGraph &CG) { + auto callNode = CG[&F]; + for (unsigned i = 0; i < callNode->size(); i++) { + if ((*callNode)[i]->getFunction() == &F) + return true; + } + return false; +} + +void DiscoPoP::fillStartEndLineNumbers(Node *root, LoopInfo &LI) { + if (root->type != nodeTypes::cu) { + int start = -1, end = -1; + + if (root->type == nodeTypes::loop) { + for (auto i : root->childrenNodes) { + if (i->type == nodeTypes::cu) { + Loop *loop = LI.getLoopFor(i->BB); + DebugLoc dl = loop->getStartLoc(); + LID lid = 0; + lid = (fileID << LIDSIZE) + dl->getLine(); + loopStartLines[root->ID] = dputil::decodeLID(lid); + break; + } + } + } + findStartEndLineNumbers(root, start, end); + + root->startLine = start; + root->endLine = end; + } + + for (auto i : root->childrenNodes) { + fillStartEndLineNumbers(i, LI); + } +} + +void DiscoPoP::findStartEndLineNumbers(Node *root, int &start, int &end) { + if (root->type == nodeTypes::cu) { + if (start == -1 || start > root->startLine) { + start = root->startLine; + } + + if (end < root->endLine) { + end = root->endLine; + } + } + + for (auto i : root->childrenNodes) { + findStartEndLineNumbers(i, start, end); + } +} + +void DiscoPoP::getFunctionReturnLines(Region *TopRegion, Node *root) { + int lid = 0; + for (Region::block_iterator bb = TopRegion->block_begin(); bb != TopRegion->block_end(); ++bb) { + for (BasicBlock::iterator instruction = (*bb)->begin(); instruction != (*bb)->end(); ++instruction) { + if (isa(instruction)) { + lid = getLID(&*instruction, fileID); + if (lid > 0) + root->returnLines.insert(lid); + } + } + } +} \ No newline at end of file diff --git a/DiscoPoP/utils/variables/defLine.cpp b/DiscoPoP/utils/variables/defLine.cpp new file mode 100644 index 000000000..308bebc0f --- /dev/null +++ b/DiscoPoP/utils/variables/defLine.cpp @@ -0,0 +1,85 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../../DiscoPoP.hpp" + +string DiscoPoP::determineVariableDefLine(Instruction *I) { + string varDefLine{"LineNotFound"}; + + bool isGlobal = false; + string varName = determineVariableName_static(&*I, isGlobal, true); + // varName = refineVarName(varName); + varName = (varName.find(".addr") == varName.npos) ? varName : varName.erase(varName.find(".addr"), 5); + // varName.erase(varName.find(".addr"), 5); + // size_t pos = varName.find(".addr"); + // if (pos != varName.npos) + // varName.erase(varName.find(".addr"), 5); + + string varType = determineVariableType(&*I); + + if (programGlobalVariablesSet.count(varName)) { + varDefLine = "GlobalVar"; + // Find definition line of global variables + GlobalVariable *globalVariable = I->getParent()->getParent()->getParent()->getGlobalVariable(StringRef(varName)); + if (globalVariable) { + MDNode *metadata = globalVariable->getMetadata("dbg"); + if (metadata) { + if (isa(metadata)) { + varDefLine = + to_string(fileID) + ":" + + to_string(cast(globalVariable->getMetadata("dbg"))->getVariable()->getLine()); + } + } + } + } + + // Start from the beginning of a function and look for the variable + Function *F = I->getFunction(); + for (Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) { + BasicBlock &BB = *FI; + for (BasicBlock::iterator BI = BB.begin(), E = BB.end(); BI != E; ++BI) { + if (DbgDeclareInst *DI = dyn_cast(BI)) { + + if (auto *N = dyn_cast(DI->getVariable())) { + if (auto *DV = dyn_cast(N)) { + if (varType.find("ARRAY") != string::npos || varType.find("STRUCT") != string::npos) { + if (DV->getName() == varName) { + varDefLine = to_string(fileID) + ":" + to_string(DV->getLine()); + break; + } + } else { + string vn = "----"; + bool isGlobal; + AllocaInst *AI = dyn_cast_or_null(DI->getAddress()); + if (AI) { + for (User *U : AI->users()) { + if (StoreInst *SI = dyn_cast(U)) { + vn = determineVariableName_static(&*SI, isGlobal, true); + break; + } else if (LoadInst *LI = dyn_cast(U)) { + vn = determineVariableName_static(&*LI, isGlobal, true); + break; + } + } + if (vn == varName || vn == varName + ".addr") { + varDefLine = to_string(fileID) + ":" + to_string(DV->getLine()); + break; + } + } + } + } + } + } + } + } + return varDefLine; +} \ No newline at end of file diff --git a/DiscoPoP/utils/variables/names.cpp b/DiscoPoP/utils/variables/names.cpp new file mode 100644 index 000000000..0d5886f65 --- /dev/null +++ b/DiscoPoP/utils/variables/names.cpp @@ -0,0 +1,251 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../../DiscoPoP.hpp" + +string DiscoPoP::getOrInsertVarName_static(string varName, IRBuilder<> &builder) { + Value *valName = NULL; + std::string vName = varName; + map::iterator pair = VarNames.find(varName); + if (pair == VarNames.end()) { + valName = builder.CreateGlobalStringPtr(StringRef(varName.c_str()), ".str"); + + VarNames[varName] = valName; + } else { + vName = pair->first; + } + + return vName; +} + +Value *DiscoPoP::getOrInsertVarName_dynamic(string varName, IRBuilder<> &builder) { + // 26.08.2022 Lukas + // update varName with original varName from Metadata + if (trueVarNamesFromMetadataMap.find(varName) == trueVarNamesFromMetadataMap.end()) { + // not found, do nothing + } else { + // found, update varName + varName = trueVarNamesFromMetadataMap[varName]; + } + + Value *vName = NULL; + map::iterator pair = VarNames.find(varName); + if (pair == VarNames.end()) { + vName = builder.CreateGlobalStringPtr(StringRef(varName.c_str()), ".str"); + VarNames[varName] = vName; + } else { + vName = pair->second; + } + return vName; +} + +string DiscoPoP::determineVariableName_static(Instruction *I, bool &isGlobalVariable /*=defaultIsGlobalVariableValue*/, + bool disable_MetadataMap) { + + assert(I && "Instruction cannot be NULL \n"); + int index = isa(I) ? 1 : 0; + Value *operand = I->getOperand(index); + + IRBuilder<> builder(I); + + if (operand == NULL) { + string retVal = getOrInsertVarName_static("", builder); + if (trueVarNamesFromMetadataMap.find(retVal) == trueVarNamesFromMetadataMap.end() || disable_MetadataMap) { + return retVal; // not found + } else { + return trueVarNamesFromMetadataMap[retVal]; // found + } + } + + if (operand->hasName()) { + //// we've found a global variable + if (isa(*operand)) { + // MOHAMMAD ADDED THIS FOR CHECKING + isGlobalVariable = true; + string retVal = string(operand->getName()); + if (trueVarNamesFromMetadataMap.find(retVal) == trueVarNamesFromMetadataMap.end() || disable_MetadataMap) { + return retVal; // not found + } else { + return trueVarNamesFromMetadataMap[retVal]; // found + } + } + if (isa(*operand)) { + GetElementPtrInst *gep = cast(operand); + Value *ptrOperand = gep->getPointerOperand(); + PointerType *PTy = cast(ptrOperand->getType()); + + // we've found a struct/class + Type *structType = pointsToStruct(PTy); + if (structType && gep->getNumOperands() > 2) { + Value *constValue = gep->getOperand(2); + if (constValue && isa(*constValue)) { + ConstantInt *idxPtr = cast(gep->getOperand(2)); + uint64_t memberIdx = *(idxPtr->getValue().getRawData()); + if (!(cast(structType))->isLiteral()) { + string strName(structType->getStructName().data()); + map::iterator it = Structs.find(strName); + if (it != Structs.end()) { + std::string ret = findStructMemberName_static(it->second, memberIdx, builder); + if (ret.size() > 0) { + string retVal = ret; + if (trueVarNamesFromMetadataMap.find(retVal) == trueVarNamesFromMetadataMap.end() || + disable_MetadataMap) { + return retVal; // not found + } else { + return trueVarNamesFromMetadataMap[retVal]; // found + } + } else { + string retVal = getOrInsertVarName_static("", builder); + if (trueVarNamesFromMetadataMap.find(retVal) == trueVarNamesFromMetadataMap.end() || + disable_MetadataMap) { + return retVal; // not found + } else { + return trueVarNamesFromMetadataMap[retVal]; // found + } + // return ret; + } + } + } + } + } + + // we've found an array + if (PTy->getPointerElementType()->getTypeID() == Type::ArrayTyID && isa(*ptrOperand)) { + return determineVariableName_static((Instruction *)ptrOperand, isGlobalVariable, false); + } + return determineVariableName_static((Instruction *)gep, isGlobalVariable, false); + } + string retVal = string(operand->getName().data()); + if (trueVarNamesFromMetadataMap.find(retVal) == trueVarNamesFromMetadataMap.end() || disable_MetadataMap) { + return retVal; // not found + } else { + return trueVarNamesFromMetadataMap[retVal]; // found + } + // return getOrInsertVarName(string(operand->getName().data()), builder); + } + + if (isa(*operand) || isa(*operand)) { + return determineVariableName_static((Instruction *)(operand), isGlobalVariable, false); + } + // if we cannot determine the name, then return * + return ""; // getOrInsertVarName("*", builder); +} + +Value *DiscoPoP::determineVariableName_dynamic(Instruction *const I) { + assert(I && "Instruction cannot be NULL \n"); + int index = isa(I) ? 1 : 0; + Value *operand = I->getOperand(index); + + IRBuilder<> builder(I); + + if (operand == NULL) { + return getOrInsertVarName_dynamic("*", builder); + } + + if (operand->hasName()) { + // we've found a global variable + if (isa(*operand)) { + DIGlobalVariable *gv = findDbgGlobalDeclare(cast(operand)); + if (gv != NULL) { + return getOrInsertVarName_dynamic(string(gv->getDisplayName().data()), builder); + } + } + if (isa(*operand)) { + GetElementPtrInst *gep = cast(operand); + Value *ptrOperand = gep->getPointerOperand(); + PointerType *PTy = cast(ptrOperand->getType()); + + // we've found a struct/class + Type *structType = pointsToStruct(PTy); + if (structType && gep->getNumOperands() > 2) { + Value *constValue = gep->getOperand(2); + if (constValue && isa(*constValue)) { + ConstantInt *idxPtr = cast(gep->getOperand(2)); + uint64_t memberIdx = *(idxPtr->getValue().getRawData()); + + StructType *STy = cast(structType); + if (!STy->isLiteral()) { + string strName(structType->getStructName().data()); + map::iterator it = Structs.find(strName); + if (it != Structs.end()) { + Value *ret = findStructMemberName(it->second, memberIdx, builder); + if (ret) + return ret; + } + } + } + } + + // we've found an array + if (PTy->getPointerElementType()->getTypeID() == Type::ArrayTyID && isa(*ptrOperand)) { + return determineVariableName_dynamic((Instruction *)ptrOperand); + } + return determineVariableName_dynamic((Instruction *)gep); + } + return getOrInsertVarName_dynamic(string(operand->getName().data()), builder); + } + + if (isa(*operand) || isa(*operand)) { + return determineVariableName_dynamic((Instruction *)(operand)); + } + if (isa(I)) { + return getOrInsertVarName_dynamic(I->getName().str(), builder); + } + // if we cannot determine the name, then return * + return getOrInsertVarName_dynamic("*", builder); +} + +void DiscoPoP::getTrueVarNamesFromMetadata(Region *TopRegion, Node *root, + std::map *trueVarNamesFromMetadataMap) { + int lid = 0; + for (Region::block_iterator bb = TopRegion->block_begin(); bb != TopRegion->block_end(); ++bb) { + for (BasicBlock::iterator instruction = (*bb)->begin(); instruction != (*bb)->end(); ++instruction) { + // search for call instructions to @llvm.dbg.declare + if (isa(instruction)) { + Function *f = (cast(instruction))->getCalledFunction(); + if (f) { + StringRef funcName = f->getName(); + if (funcName.find("llvm.dbg.declare") != string::npos) // llvm debug calls + { + CallInst *call = cast(instruction); + // check if @llvm.dbg.declare is called + // int cmp_res = + // dbg_declare.compare(call->getCalledFunction()->getName().str()); + // if(cmp_res == 0){ + // call to @llvm.dbg.declare found + // extract original and working variable name + string SRCVarName; + string IRVarName; + + Metadata *Meta = cast(call->getOperand(0))->getMetadata(); + if (isa(Meta)) { + Value *V = cast(Meta)->getValue(); + IRVarName = V->getName().str(); + } + DIVariable *V = cast(cast(call->getOperand(1))->getMetadata()); + SRCVarName = V->getName().str(); + + // add to trueVarNamesFromMetadataMap + // overwrite entry if already existing + if (trueVarNamesFromMetadataMap->find(IRVarName) == trueVarNamesFromMetadataMap->end()) { + // not found + trueVarNamesFromMetadataMap->insert(std::pair(IRVarName, SRCVarName)); + } else { + // found + (*trueVarNamesFromMetadataMap)[IRVarName] = SRCVarName; + } + } + } + } + } + } +} diff --git a/DiscoPoP/utils/variables/types.cpp b/DiscoPoP/utils/variables/types.cpp new file mode 100644 index 000000000..d3e8a5afa --- /dev/null +++ b/DiscoPoP/utils/variables/types.cpp @@ -0,0 +1,53 @@ +/* + * This file is part of the DiscoPoP software + * (http://www.discopop.tu-darmstadt.de) + * + * Copyright (c) 2020, Technische Universitaet Darmstadt, Germany + * + * This software may be modified and distributed under the terms of + * the 3-Clause BSD License. See the LICENSE file in the package base + * directory for details. + * + */ + +#include "../../DiscoPoP.hpp" + +string DiscoPoP::determineVariableType(Instruction *I) { + string s = ""; + string type_str; + int index = isa(I) ? 1 : 0; + raw_string_ostream rso(type_str); + (*((I->getOperand(index))->getType())).print(rso); + + Value *operand = I->getOperand(index); + + if (operand->hasName()) { + if (isa(*operand)) { + GetElementPtrInst *gep = cast(operand); + Value *ptrOperand = gep->getPointerOperand(); + PointerType *PTy = cast(ptrOperand->getType()); + // we've found a struct/class + Type *structType = pointsToStruct(PTy); + if (structType && gep->getNumOperands() > 2) { + s = "STRUCT,"; + } + + // we've found an array + if (PTy->getPointerElementType()->getTypeID() == Type::ArrayTyID) { + s = "ARRAY,"; + } else { + // check if previous instruction is a GEP as well. If so, an Array has + // been found (e.g. double**) + Value *prevInst = cast(gep)->getOperand(0); + if (isa(prevInst)) { + s = "ARRAY,"; + } else if (prevInst->getType()->isPointerTy()) { + s = "ARRAY,"; + } + } + } + } + + s = s + rso.str(); + return s; +} \ No newline at end of file diff --git a/rtlib/calltree/CallTree.cpp b/rtlib/calltree/CallTree.cpp index 56ae01849..d5d457a70 100644 --- a/rtlib/calltree/CallTree.cpp +++ b/rtlib/calltree/CallTree.cpp @@ -10,85 +10,77 @@ * */ -# include "CallTree.hpp" +#include "CallTree.hpp" -namespace __dp -{ - CallTree::CallTree(){ - current = make_shared(); - } +namespace __dp { +CallTree::CallTree() { current = make_shared(); } - CallTree::~CallTree(){ - } +CallTree::~CallTree() {} - unsigned int CallTree::get_node_count(){ - return call_tree_node_count.load(); - } +unsigned int CallTree::get_node_count() { return call_tree_node_count.load(); } - std::shared_ptr CallTree::get_current_node_ptr(){ - return current; - } +std::shared_ptr CallTree::get_current_node_ptr() { return current; } - void CallTree::enter_function(unsigned int function_id){ - current = make_shared(current, CallTreeNodeType::Function, function_id, 0); - } +void CallTree::enter_function(unsigned int function_id) { + current = make_shared(current, CallTreeNodeType::Function, function_id, 0); +} - void CallTree::enter_loop(unsigned int loop_id){ - current = make_shared(current, CallTreeNodeType::Loop, loop_id, 0); - } +void CallTree::enter_loop(unsigned int loop_id) { + current = make_shared(current, CallTreeNodeType::Loop, loop_id, 0); +} - void CallTree::enter_iteration(unsigned int iteration_id){ - // identify loop id of nearest loop - shared_ptr node_ptr = get_current_node_ptr(); - if(! node_ptr){ - return; - } - unsigned int loop_id = 0; - while(node_ptr.get()->get_node_type() != CallTreeNodeType::Root){ - if(node_ptr.get()->get_node_type() == CallTreeNodeType::Loop){ - // found nearest loop node - loop_id = node_ptr.get()->get_loop_or_function_id(); - break; - } - // continue search with parent node - node_ptr = node_ptr.get()->get_parent_ptr(); - } - // create iteration node - current = make_shared(node_ptr, CallTreeNodeType::Iteration, loop_id, iteration_id); +void CallTree::enter_iteration(unsigned int iteration_id) { + // identify loop id of nearest loop + shared_ptr node_ptr = get_current_node_ptr(); + if (!node_ptr) { + return; + } + unsigned int loop_id = 0; + while (node_ptr.get()->get_node_type() != CallTreeNodeType::Root) { + if (node_ptr.get()->get_node_type() == CallTreeNodeType::Loop) { + // found nearest loop node + loop_id = node_ptr.get()->get_loop_or_function_id(); + break; } + // continue search with parent node + node_ptr = node_ptr.get()->get_parent_ptr(); + } + // create iteration node + current = make_shared(node_ptr, CallTreeNodeType::Iteration, loop_id, iteration_id); +} - void CallTree::exit_function(){ - // set current to the parent of the closest function - shared_ptr node_ptr = get_current_node_ptr(); - if(! node_ptr){ - return; - } - while(node_ptr->get_node_type() != CallTreeNodeType::Root){ - if(node_ptr->get_node_type() == CallTreeNodeType::Function){ - // found closest function node - break; - } - // continue search with parent - node_ptr = node_ptr->get_parent_ptr(); - } - current = node_ptr->get_parent_ptr(); +void CallTree::exit_function() { + // set current to the parent of the closest function + shared_ptr node_ptr = get_current_node_ptr(); + if (!node_ptr) { + return; + } + while (node_ptr->get_node_type() != CallTreeNodeType::Root) { + if (node_ptr->get_node_type() == CallTreeNodeType::Function) { + // found closest function node + break; } + // continue search with parent + node_ptr = node_ptr->get_parent_ptr(); + } + current = node_ptr->get_parent_ptr(); +} - void CallTree::exit_loop(){ - // set current to the parent of the closest loop - shared_ptr node_ptr = get_current_node_ptr(); - if(! node_ptr){ - return; - } - while(node_ptr->get_node_type() != CallTreeNodeType::Root){ - if(node_ptr->get_node_type() == CallTreeNodeType::Loop){ - // found closest loop node - break; - } - // continue search with parent - node_ptr = node_ptr->get_parent_ptr(); - } - current = node_ptr->get_parent_ptr(); +void CallTree::exit_loop() { + // set current to the parent of the closest loop + shared_ptr node_ptr = get_current_node_ptr(); + if (!node_ptr) { + return; + } + while (node_ptr->get_node_type() != CallTreeNodeType::Root) { + if (node_ptr->get_node_type() == CallTreeNodeType::Loop) { + // found closest loop node + break; } + // continue search with parent + node_ptr = node_ptr->get_parent_ptr(); + } + current = node_ptr->get_parent_ptr(); +} } // namespace __dp diff --git a/rtlib/calltree/CallTree.hpp b/rtlib/calltree/CallTree.hpp index 1e9f561a4..b22bd113b 100644 --- a/rtlib/calltree/CallTree.hpp +++ b/rtlib/calltree/CallTree.hpp @@ -14,29 +14,28 @@ #include "../DPUtils.hpp" -#include -#include "CallTreeNode.hpp" #include "CallTreeGlobals.hpp" +#include "CallTreeNode.hpp" +#include #include namespace __dp { class CallTree { public: - CallTree(); - ~CallTree(); - void enter_function(unsigned int function_id); - void exit_function(); - void enter_loop(unsigned int loop_id); - void exit_loop(); - void enter_iteration(unsigned int iteration_id); - // exit_iteration not possible, as determining the iteration end is not trivial - unsigned int get_node_count(); - std::shared_ptr get_current_node_ptr(); + CallTree(); + ~CallTree(); + void enter_function(unsigned int function_id); + void exit_function(); + void enter_loop(unsigned int loop_id); + void exit_loop(); + void enter_iteration(unsigned int iteration_id); + // exit_iteration not possible, as determining the iteration end is not trivial + unsigned int get_node_count(); + std::shared_ptr get_current_node_ptr(); private: - std::shared_ptr current; - + std::shared_ptr current; }; } // namespace __dp diff --git a/rtlib/calltree/CallTreeNode.cpp b/rtlib/calltree/CallTreeNode.cpp index ac3684073..c6e81d78e 100644 --- a/rtlib/calltree/CallTreeNode.cpp +++ b/rtlib/calltree/CallTreeNode.cpp @@ -15,60 +15,48 @@ namespace __dp { -CallTreeNode::CallTreeNode(){ - parent_ptr = nullptr; - type = CallTreeNodeType::Root; - loop_or_function_id = 0; - iteration_id = 0; - call_tree_node_count += 1; -} - -CallTreeNode::CallTreeNode(shared_ptr parent_ptr, CallTreeNodeType type, unsigned int loop_or_function_id, unsigned int arg_iteration_id): parent_ptr(parent_ptr), type(type), loop_or_function_id(loop_or_function_id){ - if(type == CallTreeNodeType::Iteration){ - iteration_id = arg_iteration_id; +CallTreeNode::CallTreeNode() { + parent_ptr = nullptr; + type = CallTreeNodeType::Root; + loop_or_function_id = 0; + iteration_id = 0; + call_tree_node_count += 1; +} + +CallTreeNode::CallTreeNode(shared_ptr parent_ptr, CallTreeNodeType type, unsigned int loop_or_function_id, + unsigned int arg_iteration_id) + : parent_ptr(parent_ptr), type(type), loop_or_function_id(loop_or_function_id) { + if (type == CallTreeNodeType::Iteration) { + iteration_id = arg_iteration_id; + } else { + iteration_id = 0; + } + call_tree_node_count += 1; +} + +CallTreeNode::~CallTreeNode() { call_tree_node_count -= 1; } + +bool CallTreeNode::operator==(const CallTreeNode &other) const { + // && (iteration_id == other.iteration_id) ignore loop id + if ((type == other.type) && (loop_or_function_id == other.loop_or_function_id)) { + if (parent_ptr && other.parent_ptr) { + if (parent_ptr.get() == other.parent_ptr.get()) { + return true; + } + return false; } - else{ - iteration_id = 0; - } - call_tree_node_count += 1; + return false; + } else { + return false; + } } -CallTreeNode::~CallTreeNode(){ - call_tree_node_count -= 1; -} +shared_ptr CallTreeNode::get_parent_ptr() { return parent_ptr; } -bool CallTreeNode::operator==(const CallTreeNode& other) const{ - // && (iteration_id == other.iteration_id) ignore loop id - if((type == other.type) && (loop_or_function_id == other.loop_or_function_id) ){ - if(parent_ptr && other.parent_ptr){ - if(parent_ptr.get() == other.parent_ptr.get()){ - return true; - } - return false; - } - return false; - } - else{ - return false; - } -} +CallTreeNodeType CallTreeNode::get_node_type() { return type; } -shared_ptr CallTreeNode::get_parent_ptr(){ - return parent_ptr; -} +unsigned int CallTreeNode::get_loop_or_function_id() { return loop_or_function_id; } -CallTreeNodeType CallTreeNode::get_node_type(){ - return type; -} - -unsigned int CallTreeNode::get_loop_or_function_id(){ - return loop_or_function_id; -} - -unsigned int CallTreeNode::get_iteration_id(){ - return iteration_id; -} +unsigned int CallTreeNode::get_iteration_id() { return iteration_id; } } // namespace __dp - - diff --git a/rtlib/calltree/CallTreeNode.hpp b/rtlib/calltree/CallTreeNode.hpp index 4a1f5b214..4a5fac0d3 100644 --- a/rtlib/calltree/CallTreeNode.hpp +++ b/rtlib/calltree/CallTreeNode.hpp @@ -13,8 +13,8 @@ #pragma once #include "../DPUtils.hpp" -#include "CallTreeNodeType.hpp" #include "CallTreeGlobals.hpp" +#include "CallTreeNodeType.hpp" #include @@ -22,20 +22,21 @@ namespace __dp { class CallTreeNode { public: - CallTreeNode(); - CallTreeNode(shared_ptr parent_ptr, CallTreeNodeType type, unsigned int loop_or_function_id, unsigned int iteration_id); - ~CallTreeNode(); - bool operator==(const CallTreeNode& other) const; - shared_ptr get_parent_ptr(); - CallTreeNodeType get_node_type(); - unsigned int get_loop_or_function_id(); - unsigned int get_iteration_id(); // only relevant for iteration type nodes, else always 0 + CallTreeNode(); + CallTreeNode(shared_ptr parent_ptr, CallTreeNodeType type, unsigned int loop_or_function_id, + unsigned int iteration_id); + ~CallTreeNode(); + bool operator==(const CallTreeNode &other) const; + shared_ptr get_parent_ptr(); + CallTreeNodeType get_node_type(); + unsigned int get_loop_or_function_id(); + unsigned int get_iteration_id(); // only relevant for iteration type nodes, else always 0 private: - CallTreeNodeType type; - unsigned int loop_or_function_id; // id of the loop or function that is represented by the current node - unsigned int iteration_id; - shared_ptr parent_ptr; - atomic* node_count_ptr; + CallTreeNodeType type; + unsigned int loop_or_function_id; // id of the loop or function that is represented by the current node + unsigned int iteration_id; + shared_ptr parent_ptr; + atomic *node_count_ptr; }; } // namespace __dp diff --git a/rtlib/calltree/CallTreeNodeType.hpp b/rtlib/calltree/CallTreeNodeType.hpp index eeb8d196f..10bb0369a 100644 --- a/rtlib/calltree/CallTreeNodeType.hpp +++ b/rtlib/calltree/CallTreeNodeType.hpp @@ -15,10 +15,5 @@ #include "../DPUtils.hpp" namespace __dp { - enum class CallTreeNodeType { - Function, - Loop, - Iteration, - Root - }; +enum class CallTreeNodeType { Function, Loop, Iteration, Root }; } // namespace __dp diff --git a/rtlib/calltree/DependencyMetadata.cpp b/rtlib/calltree/DependencyMetadata.cpp index 433b04578..9834a34a2 100644 --- a/rtlib/calltree/DependencyMetadata.cpp +++ b/rtlib/calltree/DependencyMetadata.cpp @@ -12,80 +12,83 @@ #include "DependencyMetadata.hpp" -namespace __dp{ - DependencyMetadata::DependencyMetadata(MetaDataQueueElement mdqe, - std::set arg_intra_call_dependencies, std::set arg_intra_iteration_dependencies, - std::set arg_inter_call_dependencies, std::set arg_inter_iteration_dependencies, - std::set arg_sink_ancestors, std::set arg_source_ancestors): - type(mdqe.type), sink(mdqe.sink), source(mdqe.source), var(mdqe.var), AAvar(mdqe.AAvar), - intra_call_dependencies(arg_intra_call_dependencies), intra_iteration_dependencies(arg_intra_iteration_dependencies), - inter_call_dependencies(arg_inter_call_dependencies), inter_iteration_dependencies(arg_inter_iteration_dependencies), - sink_ancestors(arg_sink_ancestors), source_ancestors(arg_source_ancestors) - { - } +namespace __dp { +DependencyMetadata::DependencyMetadata(MetaDataQueueElement mdqe, std::set arg_intra_call_dependencies, + std::set arg_intra_iteration_dependencies, + std::set arg_inter_call_dependencies, + std::set arg_inter_iteration_dependencies, + std::set arg_sink_ancestors, + std::set arg_source_ancestors) + : type(mdqe.type), sink(mdqe.sink), source(mdqe.source), var(mdqe.var), AAvar(mdqe.AAvar), + intra_call_dependencies(arg_intra_call_dependencies), + intra_iteration_dependencies(arg_intra_iteration_dependencies), + inter_call_dependencies(arg_inter_call_dependencies), + inter_iteration_dependencies(arg_inter_iteration_dependencies), sink_ancestors(arg_sink_ancestors), + source_ancestors(arg_source_ancestors) {} - bool DependencyMetadata::operator==(const DependencyMetadata& other) const{ - return (type == other.type) && (sink == other.sink) && (source == other.source) && (var == other.var) - && (AAvar == other.AAvar) && (intra_call_dependencies == other.intra_call_dependencies) && (intra_iteration_dependencies == other.intra_iteration_dependencies) - && (inter_call_dependencies == other.inter_call_dependencies) && (inter_iteration_dependencies == other.inter_iteration_dependencies) - && (sink_ancestors == other.sink_ancestors) && (source_ancestors == other.source_ancestors); - } +bool DependencyMetadata::operator==(const DependencyMetadata &other) const { + return (type == other.type) && (sink == other.sink) && (source == other.source) && (var == other.var) && + (AAvar == other.AAvar) && (intra_call_dependencies == other.intra_call_dependencies) && + (intra_iteration_dependencies == other.intra_iteration_dependencies) && + (inter_call_dependencies == other.inter_call_dependencies) && + (inter_iteration_dependencies == other.inter_iteration_dependencies) && + (sink_ancestors == other.sink_ancestors) && (source_ancestors == other.source_ancestors); +} - string DependencyMetadata::toString(){ - string result = ""; - switch (type) - { - case RAW: - result += "RAW "; - break; - case WAR: - result += "WAR "; - break; - case WAW: - result += "WAW "; - break; - case INIT: - result += "INIT "; - break; - default: - break; - } - result += dputil::decodeLID(sink) + " "; - result += dputil::decodeLID(source) + " "; - result += var; - result += " "; - result += AAvar + " "; - result += "IAC["; - for(auto iac : intra_call_dependencies){ - result += dputil::decodeLID(iac) + ","; - } - result += "] "; - result += "IAI["; - for(auto iai : intra_iteration_dependencies){ - result += dputil::decodeLID(iai) + ","; - } - result += "] "; - result += "IEC["; - for(auto iec : inter_call_dependencies){ - result += dputil::decodeLID(iec) + ","; - } - result += "] "; - result += "IEI["; - for(auto iei : inter_iteration_dependencies){ - result += dputil::decodeLID(iei) + ","; - } - result += "] "; - result += "SINK_ANC["; - for(auto sink_anc : sink_ancestors){ - result += dputil::decodeLID(sink_anc) + ","; - } - result += "] "; - result += "SOURCE_ANC["; - for(auto source_anc : source_ancestors){ - result += dputil::decodeLID(source_anc) + ","; - } - result += "] "; - return result; - } +string DependencyMetadata::toString() { + string result = ""; + switch (type) { + case RAW: + result += "RAW "; + break; + case WAR: + result += "WAR "; + break; + case WAW: + result += "WAW "; + break; + case INIT: + result += "INIT "; + break; + default: + break; + } + result += dputil::decodeLID(sink) + " "; + result += dputil::decodeLID(source) + " "; + result += var; + result += " "; + result += AAvar + " "; + result += "IAC["; + for (auto iac : intra_call_dependencies) { + result += dputil::decodeLID(iac) + ","; + } + result += "] "; + result += "IAI["; + for (auto iai : intra_iteration_dependencies) { + result += dputil::decodeLID(iai) + ","; + } + result += "] "; + result += "IEC["; + for (auto iec : inter_call_dependencies) { + result += dputil::decodeLID(iec) + ","; + } + result += "] "; + result += "IEI["; + for (auto iei : inter_iteration_dependencies) { + result += dputil::decodeLID(iei) + ","; + } + result += "] "; + result += "SINK_ANC["; + for (auto sink_anc : sink_ancestors) { + result += dputil::decodeLID(sink_anc) + ","; + } + result += "] "; + result += "SOURCE_ANC["; + for (auto source_anc : source_ancestors) { + result += dputil::decodeLID(source_anc) + ","; + } + result += "] "; + return result; +} } // namespace __dp diff --git a/rtlib/calltree/DependencyMetadata.hpp b/rtlib/calltree/DependencyMetadata.hpp index 669fc8799..06d1e8426 100644 --- a/rtlib/calltree/DependencyMetadata.hpp +++ b/rtlib/calltree/DependencyMetadata.hpp @@ -16,54 +16,54 @@ #include "../runtimeFunctionsTypes.hpp" #include "MetaDataQueueElement.hpp" -namespace __dp -{ +namespace __dp { -class DependencyMetadata{ +class DependencyMetadata { public: - DependencyMetadata(MetaDataQueueElement mdqe, std::set arg_intra_call_dependencies, std::set arg_intra_iteration_dependencies, std::set arg_inter_call_dependencies, std::set arg_inter_iteration_dependencies, std::set sink_ancestors, std::set arg_source_ancestors); - DependencyMetadata(){} - bool operator==(const DependencyMetadata& other) const; - depType type; - LID sink; - LID source; - const char* var; - string AAvar; - std::set intra_call_dependencies; - std::set intra_iteration_dependencies; - std::set inter_call_dependencies; - std::set inter_iteration_dependencies; - std::set sink_ancestors; - std::set source_ancestors; - string toString(); + DependencyMetadata(MetaDataQueueElement mdqe, std::set arg_intra_call_dependencies, + std::set arg_intra_iteration_dependencies, + std::set arg_inter_call_dependencies, + std::set arg_inter_iteration_dependencies, std::set sink_ancestors, + std::set arg_source_ancestors); + DependencyMetadata() {} + bool operator==(const DependencyMetadata &other) const; + depType type; + LID sink; + LID source; + const char *var; + string AAvar; + std::set intra_call_dependencies; + std::set intra_iteration_dependencies; + std::set inter_call_dependencies; + std::set inter_iteration_dependencies; + std::set sink_ancestors; + std::set source_ancestors; + string toString(); }; } // namespace __dp -template <> -struct std::hash<__dp::DependencyMetadata> -{ - std::size_t operator()(const __dp::DependencyMetadata& k) const - { - using boost::hash_value; +template <> struct std::hash<__dp::DependencyMetadata> { + std::size_t operator()(const __dp::DependencyMetadata &k) const { using boost::hash_combine; + using boost::hash_value; // Start with a hash value of 0 . std::size_t seed = 0; // Modify 'seed' by XORing and bit-shifting in // one member of 'Key' after the other: - hash_combine(seed,hash_value(k.type)); - hash_combine(seed,hash_value(k.sink)); - hash_combine(seed,hash_value(k.source)); - hash_combine(seed,hash_value(k.var)); - hash_combine(seed,hash_value(k.AAvar)); - hash_combine(seed,hash_value(k.intra_call_dependencies)); - hash_combine(seed,hash_value(k.intra_iteration_dependencies)); - hash_combine(seed,hash_value(k.inter_call_dependencies)); - hash_combine(seed,hash_value(k.inter_iteration_dependencies)); - hash_combine(seed,hash_value(k.sink_ancestors)); - hash_combine(seed,hash_value(k.source_ancestors)); + hash_combine(seed, hash_value(k.type)); + hash_combine(seed, hash_value(k.sink)); + hash_combine(seed, hash_value(k.source)); + hash_combine(seed, hash_value(k.var)); + hash_combine(seed, hash_value(k.AAvar)); + hash_combine(seed, hash_value(k.intra_call_dependencies)); + hash_combine(seed, hash_value(k.intra_iteration_dependencies)); + hash_combine(seed, hash_value(k.inter_call_dependencies)); + hash_combine(seed, hash_value(k.inter_iteration_dependencies)); + hash_combine(seed, hash_value(k.sink_ancestors)); + hash_combine(seed, hash_value(k.source_ancestors)); // Return the result. return seed; diff --git a/rtlib/calltree/MetaDataQueue.cpp b/rtlib/calltree/MetaDataQueue.cpp index 61b13b8eb..6927027d2 100644 --- a/rtlib/calltree/MetaDataQueue.cpp +++ b/rtlib/calltree/MetaDataQueue.cpp @@ -15,125 +15,121 @@ #include "../../share/include/timer.hpp" #include "../runtimeFunctionsGlobals.hpp" -namespace __dp -{ - // TODO - MetaDataQueue::MetaDataQueue(int worker_count){ - finalize_queue = false; - - if(worker_count < 1){ - worker_count = 1; - // serial execution - } - for (size_t i = 0; i < worker_count; ++i) - { - // FIX: unnötiges move - threads.emplace_back(std::thread(processQueue, this)); - } - } - - MetaDataQueue::~MetaDataQueue(){ - } - - void MetaDataQueue::insert(MetaDataQueueElement && mdqe){ - const auto calltree_timer = Timer(timers, TimerRegion::ADD_DEP_CALLTREE_REGISTER_METADATAQUEUEELEMENT); - if(finalize_queue){ - return; - } - - // drop the element, if it was already enqueued - bool mdqe_already_enqueued = false; - // check if an equal element was already processed - enqueued_mtx.lock(); - - //mdqe_already_enqueued = enqueued.find(mdqe) != enqueued.end(); - auto contained = enqueued.insert(mdqe); - mdqe_already_enqueued = ! contained.second; - enqueued_mtx.unlock(); - - mdqe_already_enqueued = ! contained.second; - - if(mdqe_already_enqueued){ - // element already inserted to queue before - return; - } - - // insert mdqe to queue - std::lock_guard lock(queue_mtx); - queue.push(std::move(mdqe)); - //cout << "insert: " << mdqe.toString() << "\n"; - } - - int MetaDataQueue::get_size(){ - std::lock_guard lock(queue_mtx); - return queue.size(); - } - - void MetaDataQueue::blocking_finalize_queue(){ - finalize_queue = true; - // join threads - for (auto &t : threads){ - t.join(); - } - - // print results - cout << "RESULTS: \n"; - for(auto dmd: results){ - cout << dmd.toString() << "\n"; - } - - // output to file - std::cout << "Outputting dependency metadata... "; - std::ifstream ifile; - std::string line; - std::ofstream ofile; - std::string tmp(getenv("DOT_DISCOPOP_PROFILER")); - // output information about the loops - tmp += "/dependency_metadata.txt"; - ofile.open(tmp.data()); - ofile << "# IAC : intra-call-dependency \n"; - ofile << "# IAI : intra-iteration-dependency \n"; - ofile << "# IEC : inter-call-dependency \n"; - ofile << "# IEI : inter-iteration-dependency \n"; - ofile << "# SINK_ANC : entered functions and loops for sink location \n"; - ofile << "# SOURCE_ANC : entered functions and loops for source location \n"; - ofile << "# Format: \n"; - for (auto dmd : results) { - ofile << dmd.toString() << "\n"; - } - ofile.close(); - } - - void processQueue(MetaDataQueue* mdq){ - const auto calltree_timer = Timer(timers, TimerRegion::METADATAQUEUE_PROCESSQUEUE); - while(!(mdq->finalize_queue && (mdq->get_size() == 0))){ - mdq->queue_mtx.lock(); - // try fetching an element from the queue - if(mdq->queue.size() != 0){ - const auto calltree_timer = Timer(timers, TimerRegion::METADATAQUEUE_PROCESSQUEUE_FETCH); - - // fetch element from the queue - MetaDataQueueElement mdqe = mdq->queue.front(); - mdq->queue.pop(); - //std::cout << "fetched. Remaining: " << mdq->queue.size() << "\n"; - // release queue lock - mdq->queue_mtx.unlock(); - - // process element - //DependencyMetadata metadata = processQueueElement(mdqe); - - // save metadata to results - mdq->results_mtx.lock(); - mdq->results.push_back(metadata); - mdq->results_mtx.unlock(); - } - else{ - // release lock - mdq->queue_mtx.unlock(); - // sleep 5 milliseconds - std::this_thread::sleep_for(std::chrono::milliseconds(5)); - } - } +namespace __dp { +// TODO +MetaDataQueue::MetaDataQueue(int worker_count) { + finalize_queue = false; + + if (worker_count < 1) { + worker_count = 1; + // serial execution + } + for (size_t i = 0; i < worker_count; ++i) { + // FIX: unnötiges move + threads.emplace_back(std::thread(processQueue, this)); + } +} + +MetaDataQueue::~MetaDataQueue() {} + +void MetaDataQueue::insert(MetaDataQueueElement &&mdqe) { + const auto calltree_timer = Timer(timers, TimerRegion::ADD_DEP_CALLTREE_REGISTER_METADATAQUEUEELEMENT); + if (finalize_queue) { + return; + } + + // drop the element, if it was already enqueued + bool mdqe_already_enqueued = false; + // check if an equal element was already processed + enqueued_mtx.lock(); + + // mdqe_already_enqueued = enqueued.find(mdqe) != enqueued.end(); + auto contained = enqueued.insert(mdqe); + mdqe_already_enqueued = !contained.second; + enqueued_mtx.unlock(); + + mdqe_already_enqueued = !contained.second; + + if (mdqe_already_enqueued) { + // element already inserted to queue before + return; + } + + // insert mdqe to queue + std::lock_guard lock(queue_mtx); + queue.push(std::move(mdqe)); + // cout << "insert: " << mdqe.toString() << "\n"; +} + +int MetaDataQueue::get_size() { + std::lock_guard lock(queue_mtx); + return queue.size(); +} + +void MetaDataQueue::blocking_finalize_queue() { + finalize_queue = true; + // join threads + for (auto &t : threads) { + t.join(); + } + + // print results + cout << "RESULTS: \n"; + for (auto dmd : results) { + cout << dmd.toString() << "\n"; + } + + // output to file + std::cout << "Outputting dependency metadata... "; + std::ifstream ifile; + std::string line; + std::ofstream ofile; + std::string tmp(getenv("DOT_DISCOPOP_PROFILER")); + // output information about the loops + tmp += "/dependency_metadata.txt"; + ofile.open(tmp.data()); + ofile << "# IAC : intra-call-dependency \n"; + ofile << "# IAI : intra-iteration-dependency \n"; + ofile << "# IEC : inter-call-dependency \n"; + ofile << "# IEI : inter-iteration-dependency \n"; + ofile << "# SINK_ANC : entered functions and loops for sink location \n"; + ofile << "# SOURCE_ANC : entered functions and loops for source location \n"; + ofile << "# Format: \n"; + for (auto dmd : results) { + ofile << dmd.toString() << "\n"; + } + ofile.close(); +} + +void processQueue(MetaDataQueue *mdq) { + const auto calltree_timer = Timer(timers, TimerRegion::METADATAQUEUE_PROCESSQUEUE); + while (!(mdq->finalize_queue && (mdq->get_size() == 0))) { + mdq->queue_mtx.lock(); + // try fetching an element from the queue + if (mdq->queue.size() != 0) { + const auto calltree_timer = Timer(timers, TimerRegion::METADATAQUEUE_PROCESSQUEUE_FETCH); + + // fetch element from the queue + MetaDataQueueElement mdqe = mdq->queue.front(); + mdq->queue.pop(); + // std::cout << "fetched. Remaining: " << mdq->queue.size() << "\n"; + // release queue lock + mdq->queue_mtx.unlock(); + + // process element + // DependencyMetadata metadata = processQueueElement(mdqe); + + // save metadata to results + mdq->results_mtx.lock(); + mdq->results.push_back(metadata); + mdq->results_mtx.unlock(); + } else { + // release lock + mdq->queue_mtx.unlock(); + // sleep 5 milliseconds + std::this_thread::sleep_for(std::chrono::milliseconds(5)); } + } +} } // namespace __dp \ No newline at end of file diff --git a/rtlib/calltree/MetaDataQueue.hpp b/rtlib/calltree/MetaDataQueue.hpp index fb3ed89ed..fdda78ed3 100644 --- a/rtlib/calltree/MetaDataQueue.hpp +++ b/rtlib/calltree/MetaDataQueue.hpp @@ -12,43 +12,38 @@ #pragma once +#include "DependencyMetadata.hpp" +#include "MetaDataQueueElement.hpp" +#include #include #include #include -#include #include +#include #include -#include -#include "MetaDataQueueElement.hpp" -#include "DependencyMetadata.hpp" - -namespace __dp -{ -class MetaDataQueue{ +namespace __dp { +class MetaDataQueue { public: - MetaDataQueue(int worker_count); // worker_count: minimum 1 - ~MetaDataQueue(); - void insert(MetaDataQueueElement && mdqe); // TODO optimization potential, do not use copies here! - const std::set& get_metadata(); - int get_size(); - void blocking_finalize_queue(); - bool finalize_queue; - std::mutex queue_mtx; - std::queue queue; - std::mutex results_mtx; - std::vector results; - std::mutex enqueued_mtx; - std::unordered_set enqueued; + MetaDataQueue(int worker_count); // worker_count: minimum 1 + ~MetaDataQueue(); + void insert(MetaDataQueueElement &&mdqe); // TODO optimization potential, do not use copies here! + const std::set &get_metadata(); + int get_size(); + void blocking_finalize_queue(); + bool finalize_queue; + std::mutex queue_mtx; + std::queue queue; + std::mutex results_mtx; + std::vector results; + std::mutex enqueued_mtx; + std::unordered_set enqueued; private: - std::vector threads; - + std::vector threads; }; -static void processQueue(MetaDataQueue* mdq); +static void processQueue(MetaDataQueue *mdq); static DependencyMetadata processQueueElement(MetaDataQueueElement mdqe); - - } // namespace __dp \ No newline at end of file diff --git a/rtlib/calltree/MetaDataQueueElement.cpp b/rtlib/calltree/MetaDataQueueElement.cpp index be32447c1..a38d00846 100644 --- a/rtlib/calltree/MetaDataQueueElement.cpp +++ b/rtlib/calltree/MetaDataQueueElement.cpp @@ -12,44 +12,48 @@ #include "MetaDataQueueElement.hpp" -namespace __dp -{ - MetaDataQueueElement::MetaDataQueueElement(depType arg_type, LID arg_sink, LID arg_source, const char* arg_var, string arg_AAvar, shared_ptr arg_sink_ctn, shared_ptr arg_source_ctn): - type(arg_type), sink(arg_sink), source(arg_source), var(arg_var), AAvar(arg_AAvar), sink_ctn(arg_sink_ctn), source_ctn(arg_source_ctn){ - } +namespace __dp { +MetaDataQueueElement::MetaDataQueueElement(depType arg_type, LID arg_sink, LID arg_source, const char *arg_var, + string arg_AAvar, shared_ptr arg_sink_ctn, + shared_ptr arg_source_ctn) + : type(arg_type), sink(arg_sink), source(arg_source), var(arg_var), AAvar(arg_AAvar), sink_ctn(arg_sink_ctn), + source_ctn(arg_source_ctn) {} - bool MetaDataQueueElement::operator==(const MetaDataQueueElement& other) const{ - return (type == other.type) && (sink == other.sink) && (source == other.source) && (var == other.var) - && (AAvar == other.AAvar) && (sink_ctn->get_node_type() == other.sink_ctn->get_node_type()) && (sink_ctn->get_loop_or_function_id() == other.sink_ctn->get_loop_or_function_id()) && (sink_ctn->get_iteration_id() == other.sink_ctn->get_iteration_id()) - && (source_ctn->get_node_type() == other.source_ctn->get_node_type()) && (source_ctn->get_loop_or_function_id() == other.source_ctn->get_loop_or_function_id()) && (source_ctn->get_iteration_id() == other.source_ctn->get_iteration_id()); - } +bool MetaDataQueueElement::operator==(const MetaDataQueueElement &other) const { + return (type == other.type) && (sink == other.sink) && (source == other.source) && (var == other.var) && + (AAvar == other.AAvar) && (sink_ctn->get_node_type() == other.sink_ctn->get_node_type()) && + (sink_ctn->get_loop_or_function_id() == other.sink_ctn->get_loop_or_function_id()) && + (sink_ctn->get_iteration_id() == other.sink_ctn->get_iteration_id()) && + (source_ctn->get_node_type() == other.source_ctn->get_node_type()) && + (source_ctn->get_loop_or_function_id() == other.source_ctn->get_loop_or_function_id()) && + (source_ctn->get_iteration_id() == other.source_ctn->get_iteration_id()); +} - string MetaDataQueueElement::toString(){ - string result = "MDQE( "; - switch (type) - { - case RAW: - result += "RAW "; - break; - case WAR: - result += "WAR "; - break; - case WAW: - result += "WAW "; - break; - default: - break; - } - result += dputil::decodeLID(sink) + " - " + dputil::decodeLID(source) + " "; - result += var; - result += " "; - result += AAvar + " "; - result += "sink_ctn: " + to_string(sink_ctn->get_loop_or_function_id()) + " "; - result += "it: " + to_string(sink_ctn->get_iteration_id()) + " "; - result += "source_ctn: " + to_string(source_ctn->get_loop_or_function_id()) + " "; - result += "it: " + to_string(source_ctn->get_iteration_id()) + " "; - result += ")"; - return result; - } +string MetaDataQueueElement::toString() { + string result = "MDQE( "; + switch (type) { + case RAW: + result += "RAW "; + break; + case WAR: + result += "WAR "; + break; + case WAW: + result += "WAW "; + break; + default: + break; + } + result += dputil::decodeLID(sink) + " - " + dputil::decodeLID(source) + " "; + result += var; + result += " "; + result += AAvar + " "; + result += "sink_ctn: " + to_string(sink_ctn->get_loop_or_function_id()) + " "; + result += "it: " + to_string(sink_ctn->get_iteration_id()) + " "; + result += "source_ctn: " + to_string(source_ctn->get_loop_or_function_id()) + " "; + result += "it: " + to_string(source_ctn->get_iteration_id()) + " "; + result += ")"; + return result; +} } // namespace __dp \ No newline at end of file diff --git a/rtlib/calltree/MetaDataQueueElement.hpp b/rtlib/calltree/MetaDataQueueElement.hpp index a642aff0e..924503a9e 100644 --- a/rtlib/calltree/MetaDataQueueElement.hpp +++ b/rtlib/calltree/MetaDataQueueElement.hpp @@ -13,53 +13,50 @@ #pragma once #include "../DPUtils.hpp" +#include "../runtimeFunctionsTypes.hpp" #include "CallTreeNode.hpp" -#include #include -#include "../runtimeFunctionsTypes.hpp" +#include -namespace __dp -{ +namespace __dp { -class MetaDataQueueElement{ +class MetaDataQueueElement { public: - MetaDataQueueElement(depType arg_type, LID arg_sink, LID arg_source, const char* arg_var, string arg_AAvar, shared_ptr arg_sink_ctn, shared_ptr arg_source_ctn); - bool operator==(const MetaDataQueueElement& other) const; - string toString(); - depType type; - LID sink; - LID source; - const char* var; - string AAvar; - shared_ptr sink_ctn; - shared_ptr source_ctn; + MetaDataQueueElement(depType arg_type, LID arg_sink, LID arg_source, const char *arg_var, string arg_AAvar, + shared_ptr arg_sink_ctn, shared_ptr arg_source_ctn); + bool operator==(const MetaDataQueueElement &other) const; + string toString(); + depType type; + LID sink; + LID source; + const char *var; + string AAvar; + shared_ptr sink_ctn; + shared_ptr source_ctn; }; -} +} // namespace __dp -template <> -struct std::hash<__dp::MetaDataQueueElement> -{ - std::size_t operator()(const __dp::MetaDataQueueElement& k) const - { - using boost::hash_value; +template <> struct std::hash<__dp::MetaDataQueueElement> { + std::size_t operator()(const __dp::MetaDataQueueElement &k) const { using boost::hash_combine; + using boost::hash_value; // Start with a hash value of 0 . std::size_t seed = 0; // Modify 'seed' by XORing and bit-shifting in // one member of 'Key' after the other: - hash_combine(seed,hash_value(k.type)); - hash_combine(seed,hash_value(k.sink)); - hash_combine(seed,hash_value(k.source)); - hash_combine(seed,hash_value(k.var)); - hash_combine(seed,hash_value(k.AAvar)); - hash_combine(seed,hash_value(k.sink_ctn->get_node_type())); - hash_combine(seed,hash_value(k.sink_ctn->get_loop_or_function_id())); - hash_combine(seed,hash_value(k.sink_ctn->get_iteration_id())); - hash_combine(seed,hash_value(k.source_ctn->get_node_type())); - hash_combine(seed,hash_value(k.source_ctn->get_loop_or_function_id())); - hash_combine(seed,hash_value(k.source_ctn->get_iteration_id())); + hash_combine(seed, hash_value(k.type)); + hash_combine(seed, hash_value(k.sink)); + hash_combine(seed, hash_value(k.source)); + hash_combine(seed, hash_value(k.var)); + hash_combine(seed, hash_value(k.AAvar)); + hash_combine(seed, hash_value(k.sink_ctn->get_node_type())); + hash_combine(seed, hash_value(k.sink_ctn->get_loop_or_function_id())); + hash_combine(seed, hash_value(k.sink_ctn->get_iteration_id())); + hash_combine(seed, hash_value(k.source_ctn->get_node_type())); + hash_combine(seed, hash_value(k.source_ctn->get_loop_or_function_id())); + hash_combine(seed, hash_value(k.source_ctn->get_iteration_id())); // Return the result. return seed; diff --git a/rtlib/calltree/utils.cpp b/rtlib/calltree/utils.cpp index c330ade68..863607fde 100644 --- a/rtlib/calltree/utils.cpp +++ b/rtlib/calltree/utils.cpp @@ -15,142 +15,141 @@ #include "../runtimeFunctionsGlobals.hpp" #include -namespace __dp{ +namespace __dp { -DependencyMetadata processQueueElement(MetaDataQueueElement mdqe){ - const auto calltree_timer = Timer(timers, TimerRegion::PROCESSQUEUEELEMENT); +DependencyMetadata processQueueElement(MetaDataQueueElement mdqe) { + const auto calltree_timer = Timer(timers, TimerRegion::PROCESSQUEUEELEMENT); - //cout << "processing " << mdqe.toString() << "\n"; + // cout << "processing " << mdqe.toString() << "\n"; - shared_ptr curr_ctn_node; - // collect ancestors of sink_ctn - curr_ctn_node = mdqe.sink_ctn; - std::set> sink_ctn_ancestors; - std::set sink_ancestor_loops_and_functions; - if(curr_ctn_node){ - while(curr_ctn_node->get_node_type() != CallTreeNodeType::Root){ - if(curr_ctn_node->get_node_type() == CallTreeNodeType::Loop){ - // ignore for metadata calculation, but keep for ancestor reporting - sink_ancestor_loops_and_functions.insert(curr_ctn_node->get_loop_or_function_id()); - } - else{ - sink_ctn_ancestors.insert(curr_ctn_node); - // ancestor reporting - if(curr_ctn_node->get_node_type() == CallTreeNodeType::Function){ - sink_ancestor_loops_and_functions.insert(curr_ctn_node->get_loop_or_function_id()); - } - } - - curr_ctn_node = curr_ctn_node->get_parent_ptr(); - if(!curr_ctn_node){ - break; - } - } + shared_ptr curr_ctn_node; + // collect ancestors of sink_ctn + curr_ctn_node = mdqe.sink_ctn; + std::set> sink_ctn_ancestors; + std::set sink_ancestor_loops_and_functions; + if (curr_ctn_node) { + while (curr_ctn_node->get_node_type() != CallTreeNodeType::Root) { + if (curr_ctn_node->get_node_type() == CallTreeNodeType::Loop) { + // ignore for metadata calculation, but keep for ancestor reporting + sink_ancestor_loops_and_functions.insert(curr_ctn_node->get_loop_or_function_id()); + } else { + sink_ctn_ancestors.insert(curr_ctn_node); + // ancestor reporting + if (curr_ctn_node->get_node_type() == CallTreeNodeType::Function) { + sink_ancestor_loops_and_functions.insert(curr_ctn_node->get_loop_or_function_id()); } + } - // collect ancestors of source_ctn - curr_ctn_node = mdqe.source_ctn; - std::set> source_ctn_ancestors; - std::set source_ancestor_loops_and_functions; - if(curr_ctn_node){ - while(curr_ctn_node->get_node_type() != CallTreeNodeType::Root){ - if(curr_ctn_node->get_node_type() == CallTreeNodeType::Loop){ - // ignore for metadata calculation, but keep for ancestor reporting - source_ancestor_loops_and_functions.insert(curr_ctn_node->get_loop_or_function_id()); - } - else{ - source_ctn_ancestors.insert(curr_ctn_node); - // ancestor reporting - if(curr_ctn_node->get_node_type() == CallTreeNodeType::Function){ - source_ancestor_loops_and_functions.insert(curr_ctn_node->get_loop_or_function_id()); - } - } - - curr_ctn_node = curr_ctn_node->get_parent_ptr(); - if(!curr_ctn_node){ - break; - } - } - } + curr_ctn_node = curr_ctn_node->get_parent_ptr(); + if (!curr_ctn_node) { + break; + } + } + } - // determine common ancestors - std::set> common_ancestors; - for(auto sink_anc : sink_ctn_ancestors){ - for(auto source_anc : source_ctn_ancestors){ - if(sink_anc == source_anc){ - common_ancestors.insert(sink_anc); - } - } + // collect ancestors of source_ctn + curr_ctn_node = mdqe.source_ctn; + std::set> source_ctn_ancestors; + std::set source_ancestor_loops_and_functions; + if (curr_ctn_node) { + while (curr_ctn_node->get_node_type() != CallTreeNodeType::Root) { + if (curr_ctn_node->get_node_type() == CallTreeNodeType::Loop) { + // ignore for metadata calculation, but keep for ancestor reporting + source_ancestor_loops_and_functions.insert(curr_ctn_node->get_loop_or_function_id()); + } else { + source_ctn_ancestors.insert(curr_ctn_node); + // ancestor reporting + if (curr_ctn_node->get_node_type() == CallTreeNodeType::Function) { + source_ancestor_loops_and_functions.insert(curr_ctn_node->get_loop_or_function_id()); } + } - // determine disjoint ancestors - std::set> disjoint_sink_ancestors; - std::set> disjoint_source_ancestors; - for(auto sink_anc : sink_ctn_ancestors){ - bool contained = false; - for(auto source_anc : source_ctn_ancestors){ - if(sink_anc == source_anc){ - contained = true; - break; - } - } - if(!contained){ - disjoint_sink_ancestors.insert(sink_anc); - } - } - for(auto source_anc : source_ctn_ancestors){ - bool contained = false; - for(auto sink_anc : sink_ctn_ancestors){ - if(source_anc == sink_anc){ - contained = true; - break; - } - } - if(!contained){ - disjoint_source_ancestors.insert(source_anc); - } - } - //cout << "common: " << common_ancestors.size() << " disjoint sink: " << disjoint_sink_ancestors.size() << " source: " << disjoint_source_ancestors.size() << "\n"; + curr_ctn_node = curr_ctn_node->get_parent_ptr(); + if (!curr_ctn_node) { + break; + } + } + } - // identify intra_call and intra_iteration dependencies - std::set intra_call_dependencies; - std::set intra_iteration_dependencies; - for(auto common_anc : common_ancestors){ - if(common_anc->get_node_type() == CallTreeNodeType::Function){ - intra_call_dependencies.insert(common_anc->get_loop_or_function_id()); - } - else if(common_anc->get_node_type() == CallTreeNodeType::Iteration){ - intra_iteration_dependencies.insert(common_anc->get_loop_or_function_id()); - } - } - //cout << "intra_call: " << intra_call_dependencies.size() << " intra_iteration: " << intra_iteration_dependencies.size() << "\n"; + // determine common ancestors + std::set> common_ancestors; + for (auto sink_anc : sink_ctn_ancestors) { + for (auto source_anc : source_ctn_ancestors) { + if (sink_anc == source_anc) { + common_ancestors.insert(sink_anc); + } + } + } - // identify inter_call and inter_iteration dependencies - std::set inter_call_dependencies; - std::set inter_iteration_dependencies; - for(auto disjoint_sink_anc : disjoint_sink_ancestors){ - for(auto disjoint_source_anc : disjoint_source_ancestors){ - // check for inter call dependencies - if((disjoint_sink_anc->get_node_type() == CallTreeNodeType::Function ) - && (disjoint_source_anc->get_node_type() == CallTreeNodeType::Function) - && (disjoint_sink_anc->get_loop_or_function_id() == disjoint_source_anc->get_loop_or_function_id())){ - inter_call_dependencies.insert(disjoint_sink_anc->get_loop_or_function_id()); - } - // check for inter iteration dependencies - if((disjoint_sink_anc->get_node_type() == CallTreeNodeType::Iteration) - && (disjoint_source_anc->get_node_type() == CallTreeNodeType::Iteration) - && (disjoint_sink_anc->get_parent_ptr() == disjoint_source_anc->get_parent_ptr()) - && (disjoint_sink_anc->get_parent_ptr()->get_node_type() == CallTreeNodeType::Loop) - ){ - inter_iteration_dependencies.insert(disjoint_sink_anc->get_loop_or_function_id()); - } - } - } - //cout << "inter_call: " << inter_call_dependencies.size() << " inter_iteration: " << inter_iteration_dependencies.size() << "\n"; + // determine disjoint ancestors + std::set> disjoint_sink_ancestors; + std::set> disjoint_source_ancestors; + for (auto sink_anc : sink_ctn_ancestors) { + bool contained = false; + for (auto source_anc : source_ctn_ancestors) { + if (sink_anc == source_anc) { + contained = true; + break; + } + } + if (!contained) { + disjoint_sink_ancestors.insert(sink_anc); + } + } + for (auto source_anc : source_ctn_ancestors) { + bool contained = false; + for (auto sink_anc : sink_ctn_ancestors) { + if (source_anc == sink_anc) { + contained = true; + break; + } + } + if (!contained) { + disjoint_source_ancestors.insert(source_anc); + } + } + // cout << "common: " << common_ancestors.size() << " disjoint sink: " << disjoint_sink_ancestors.size() << " source: + // " << disjoint_source_ancestors.size() << "\n"; - return DependencyMetadata(mdqe, intra_call_dependencies, intra_iteration_dependencies, - inter_call_dependencies, inter_iteration_dependencies, - sink_ancestor_loops_and_functions, source_ancestor_loops_and_functions); + // identify intra_call and intra_iteration dependencies + std::set intra_call_dependencies; + std::set intra_iteration_dependencies; + for (auto common_anc : common_ancestors) { + if (common_anc->get_node_type() == CallTreeNodeType::Function) { + intra_call_dependencies.insert(common_anc->get_loop_or_function_id()); + } else if (common_anc->get_node_type() == CallTreeNodeType::Iteration) { + intra_iteration_dependencies.insert(common_anc->get_loop_or_function_id()); } + } + // cout << "intra_call: " << intra_call_dependencies.size() << " intra_iteration: " << + // intra_iteration_dependencies.size() << "\n"; + + // identify inter_call and inter_iteration dependencies + std::set inter_call_dependencies; + std::set inter_iteration_dependencies; + for (auto disjoint_sink_anc : disjoint_sink_ancestors) { + for (auto disjoint_source_anc : disjoint_source_ancestors) { + // check for inter call dependencies + if ((disjoint_sink_anc->get_node_type() == CallTreeNodeType::Function) && + (disjoint_source_anc->get_node_type() == CallTreeNodeType::Function) && + (disjoint_sink_anc->get_loop_or_function_id() == disjoint_source_anc->get_loop_or_function_id())) { + inter_call_dependencies.insert(disjoint_sink_anc->get_loop_or_function_id()); + } + // check for inter iteration dependencies + if ((disjoint_sink_anc->get_node_type() == CallTreeNodeType::Iteration) && + (disjoint_source_anc->get_node_type() == CallTreeNodeType::Iteration) && + (disjoint_sink_anc->get_parent_ptr() == disjoint_source_anc->get_parent_ptr()) && + (disjoint_sink_anc->get_parent_ptr()->get_node_type() == CallTreeNodeType::Loop)) { + inter_iteration_dependencies.insert(disjoint_sink_anc->get_loop_or_function_id()); + } + } + } + // cout << "inter_call: " << inter_call_dependencies.size() << " inter_iteration: " << + // inter_iteration_dependencies.size() << "\n"; + + return DependencyMetadata(mdqe, intra_call_dependencies, intra_iteration_dependencies, inter_call_dependencies, + inter_iteration_dependencies, sink_ancestor_loops_and_functions, + source_ancestor_loops_and_functions); +} } // namespace __dp \ No newline at end of file diff --git a/rtlib/calltree/utils.hpp b/rtlib/calltree/utils.hpp index c0397ceb0..e823db615 100644 --- a/rtlib/calltree/utils.hpp +++ b/rtlib/calltree/utils.hpp @@ -13,6 +13,6 @@ #include "DependencyMetadata.hpp" #include "MetaDataQueueElement.hpp" -namespace __dp{ - DependencyMetadata processQueueElement(MetaDataQueueElement mdqe); +namespace __dp { +DependencyMetadata processQueueElement(MetaDataQueueElement mdqe); } // namespace __dp diff --git a/rtlib/injected_functions/dp_finalize.cpp b/rtlib/injected_functions/dp_finalize.cpp index e655d1b52..b05fec996 100644 --- a/rtlib/injected_functions/dp_finalize.cpp +++ b/rtlib/injected_functions/dp_finalize.cpp @@ -156,11 +156,10 @@ void __dp_finalize(LID lid) { delete function_manager; delete loop_manager; - #ifdef DP_CALLTREE_PROFILING delete call_tree; - //delete metadata_queue; - // output metadata to file + // delete metadata_queue; + // output metadata to file std::cout << "Outputting dependency metadata... "; std::ifstream ifile; std::string line; @@ -177,14 +176,13 @@ void __dp_finalize(LID lid) { ofile << "# SOURCE_ANC : entered functions and loops for source location \n"; ofile << "# Format: \n"; for (auto dmd : *dependency_metadata_results) { - ofile << dmd.toString() << "\n"; + ofile << dmd.toString() << "\n"; } ofile.close(); delete dependency_metadata_results_mtx; delete dependency_metadata_results; #endif - *out << dputil::decodeLID(lid) << " END program" << endl; out->flush(); out->close(); diff --git a/rtlib/injected_functions/dp_func_entry.cpp b/rtlib/injected_functions/dp_func_entry.cpp index 6e2b7d1eb..0691507a6 100644 --- a/rtlib/injected_functions/dp_func_entry.cpp +++ b/rtlib/injected_functions/dp_func_entry.cpp @@ -60,7 +60,7 @@ void __dp_func_entry(LID lid, int32_t isStart) { memory_manager = new MemoryManager(); #if DP_CALLTREE_PROFILING call_tree = new CallTree(); - //metadata_queue = new MetaDataQueue(6); // TODO: add Worker argument + // metadata_queue = new MetaDataQueue(6); // TODO: add Worker argument dependency_metadata_results_mtx = new std::mutex(); dependency_metadata_results = new std::unordered_set(); #endif @@ -136,7 +136,6 @@ void __dp_func_entry(LID lid, int32_t isStart) { call_tree->enter_function(lid); #endif - if (isStart) *out << "START " << dputil::decodeLID(lid) << endl; diff --git a/rtlib/injected_functions/dp_loop_entry.cpp b/rtlib/injected_functions/dp_loop_entry.cpp index a4ea0c5e1..d9cecf41c 100644 --- a/rtlib/injected_functions/dp_loop_entry.cpp +++ b/rtlib/injected_functions/dp_loop_entry.cpp @@ -65,8 +65,8 @@ void __dp_loop_entry(LID lid, int32_t loopID) { #endif #ifdef DP_CALLTREE_PROFILING - call_tree->enter_loop(lid); - call_tree->enter_iteration(0); + call_tree->enter_loop(lid); + call_tree->enter_iteration(0); #endif } else { @@ -93,7 +93,7 @@ void __dp_loop_entry(LID lid, int32_t loopID) { #endif #ifdef DP_CALLTREE_PROFILING - call_tree->enter_iteration(0); + call_tree->enter_iteration(0); #endif } } diff --git a/rtlib/memory/PerfectShadow.hpp b/rtlib/memory/PerfectShadow.hpp index 856362b15..7c9cfd117 100644 --- a/rtlib/memory/PerfectShadow.hpp +++ b/rtlib/memory/PerfectShadow.hpp @@ -110,8 +110,7 @@ class PerfectShadow2 : public AbstractShadow { write_cache.reserve(1024); } - ~PerfectShadow2() { - } + ~PerfectShadow2() {} sigElement testInRead(const std::int64_t memAddr) noexcept { return read_cache[memAddr]; } diff --git a/rtlib/runtimeFunctions.cpp b/rtlib/runtimeFunctions.cpp index 15a634bb7..0ee7de481 100644 --- a/rtlib/runtimeFunctions.cpp +++ b/rtlib/runtimeFunctions.cpp @@ -17,12 +17,12 @@ #include "../share/include/debug_print.hpp" #include "../share/include/timer.hpp" +#include "calltree/utils.hpp" #include "injected_functions/all.hpp" #include "loop/Makros.hpp" #include "memory/PerfectShadow.hpp" #include "memory/ShadowMemory.hpp" #include "memory/Signature.hpp" -#include "calltree/utils.hpp" #include #include @@ -56,13 +56,12 @@ namespace __dp { /******* Helper functions *******/ - #if DP_CALLTREE_PROFILING -void addDep(depType type, LID curr, LID depOn, const char *var, - string AAvar, ADDR addr, std::unordered_map>* thread_private_write_addr_to_call_tree_node_map, std::unordered_map>* thread_private_read_addr_to_call_tree_node_map){ +void addDep(depType type, LID curr, LID depOn, const char *var, string AAvar, ADDR addr, + std::unordered_map> *thread_private_write_addr_to_call_tree_node_map, + std::unordered_map> *thread_private_read_addr_to_call_tree_node_map) { #else -void addDep(depType type, LID curr, LID depOn, const char *var, - string AAvar, ADDR addr){ +void addDep(depType type, LID curr, LID depOn, const char *var, string AAvar, ADDR addr) { #endif #ifdef DP_INTERNAL_TIMER @@ -90,51 +89,67 @@ void addDep(depType type, LID curr, LID depOn, const char *var, posInDeps->second->insert(Dep(type, depOn, var, AAvar)); } - #if DP_CALLTREE_PROFILING - // register dependency for call_tree based metadata calculation + // register dependency for call_tree based metadata calculation DependencyMetadata dmd; - switch(type){ - case RAW: - // register metadata calculation - //cout << "Register metadata calculation: RAW " << decodeLID(curr) << " " << decodeLID(depOn) << " " << var << " (" << (*thread_private_write_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << (*thread_private_write_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ") " << " (" << (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ")\n"; - - // process directly - dmd = processQueueElement(MetaDataQueueElement(type, curr, depOn, var, AAvar, (*thread_private_read_addr_to_call_tree_node_map)[addr], (*thread_private_write_addr_to_call_tree_node_map)[addr])); - dependency_metadata_results_mtx->lock(); - dependency_metadata_results->insert(dmd); - dependency_metadata_results_mtx->unlock(); - - //metadata_queue->insert(); // optimization potential: do not use copies here! - break; - case WAR: - // update write - // register metadata calculation - //cout << "Register metadata calculation: WAR " << decodeLID(curr) << " " << decodeLID(depOn) << " " << var << " (" << (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ") " << " (" << (*thread_private_write_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << (*thread_private_write_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ")\n"; - - dmd = processQueueElement(MetaDataQueueElement(type, curr, depOn, var, AAvar, (*thread_private_write_addr_to_call_tree_node_map)[addr], (*thread_private_read_addr_to_call_tree_node_map)[addr])); - dependency_metadata_results_mtx->lock(); - dependency_metadata_results->insert(dmd); - dependency_metadata_results_mtx->unlock(); - // metadata_queue->insert(); // optimization potential: do not use copies here! - break; - case WAW: - // register metadata calculation - //cout << "Register metadata calculation: WAW " << decodeLID(curr) << " " << decodeLID(depOn) << " " << var << " (" << (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ") " << " (" << (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ")\n"; - dmd = processQueueElement(MetaDataQueueElement(type, curr, depOn, var, AAvar, (*thread_private_write_addr_to_call_tree_node_map)[addr], (*thread_private_write_addr_to_call_tree_node_map)[addr])); - dependency_metadata_results_mtx->lock(); - dependency_metadata_results->insert(dmd); - dependency_metadata_results_mtx->unlock(); - //metadata_queue->insert(); // optimization potential: do not use copies here! - break; - case INIT: - break; - default: - break; + switch (type) { + case RAW: + // register metadata calculation + // cout << "Register metadata calculation: RAW " << decodeLID(curr) << " " << decodeLID(depOn) << " " << var << " (" + // << (*thread_private_write_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << + // (*thread_private_write_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ") " << " (" << + // (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << + // (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ")\n"; + + // process directly + dmd = processQueueElement(MetaDataQueueElement(type, curr, depOn, var, AAvar, + (*thread_private_read_addr_to_call_tree_node_map)[addr], + (*thread_private_write_addr_to_call_tree_node_map)[addr])); + dependency_metadata_results_mtx->lock(); + dependency_metadata_results->insert(dmd); + dependency_metadata_results_mtx->unlock(); + + // metadata_queue->insert(); // optimization potential: do not use copies here! + break; + case WAR: + // update write + // register metadata calculation + // cout << "Register metadata calculation: WAR " << decodeLID(curr) << " " << decodeLID(depOn) << " " << var << " (" + // << (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << + // (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ") " << " (" << + // (*thread_private_write_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << + // (*thread_private_write_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ")\n"; + + dmd = processQueueElement(MetaDataQueueElement(type, curr, depOn, var, AAvar, + (*thread_private_write_addr_to_call_tree_node_map)[addr], + (*thread_private_read_addr_to_call_tree_node_map)[addr])); + dependency_metadata_results_mtx->lock(); + dependency_metadata_results->insert(dmd); + dependency_metadata_results_mtx->unlock(); + // metadata_queue->insert(); // optimization potential: do not use copies here! + break; + case WAW: + // register metadata calculation + // cout << "Register metadata calculation: WAW " << decodeLID(curr) << " " << decodeLID(depOn) << " " << var << " (" + // << (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << + // (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ") " << " (" << + // (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << + // (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ")\n"; + dmd = processQueueElement(MetaDataQueueElement(type, curr, depOn, var, AAvar, + (*thread_private_write_addr_to_call_tree_node_map)[addr], + (*thread_private_write_addr_to_call_tree_node_map)[addr])); + dependency_metadata_results_mtx->lock(); + dependency_metadata_results->insert(dmd); + dependency_metadata_results_mtx->unlock(); + // metadata_queue->insert(); // optimization potential: do not use copies here! + break; + case INIT: + break; + default: + break; } - -#endif +#endif if (DP_DEBUG) { cout << "inserted dep [" << decodeLID(curr) << ", "; @@ -158,7 +173,6 @@ void addDep(depType type, LID curr, LID depOn, const char *var, } } - // hybrid analysis void generateStringDepMap() { #ifdef DP_RTLIB_VERBOSE @@ -380,7 +394,10 @@ void mergeDeps() { } #if DP_CALLTREE_PROFILING -void analyzeSingleAccess(__dp::AbstractShadow *SMem, __dp::AccessInfo &access, std::unordered_map>* thread_private_write_addr_to_call_tree_node_map, std::unordered_map>* thread_private_read_addr_to_call_tree_node_map) { +void analyzeSingleAccess( + __dp::AbstractShadow *SMem, __dp::AccessInfo &access, + std::unordered_map> *thread_private_write_addr_to_call_tree_node_map, + std::unordered_map> *thread_private_read_addr_to_call_tree_node_map) { #else void analyzeSingleAccess(__dp::AbstractShadow *SMem, __dp::AccessInfo &access) { #endif @@ -395,9 +412,9 @@ void analyzeSingleAccess(__dp::AbstractShadow *SMem, __dp::AccessInfo &access) { if (access.skip) { SMem->insertToRead(access.addr, access.lid); #if DP_CALLTREE_PROFILING - //cout << "Acc1 " << access.addr << " " << access.call_tree_node_ptr << "\n"; + // cout << "Acc1 " << access.addr << " " << access.call_tree_node_ptr << "\n"; (*thread_private_read_addr_to_call_tree_node_map)[access.addr] = access.call_tree_node_ptr; - //cout << "Access read succ\n"; + // cout << "Access read succ\n"; #endif return; } @@ -407,65 +424,61 @@ void analyzeSingleAccess(__dp::AbstractShadow *SMem, __dp::AccessInfo &access) { // RAW SMem->insertToRead(access.addr, access.lid); #if DP_CALLTREE_PROFILING - //cout << "Acc2 " << access.addr << " " << access.call_tree_node_ptr << "\n"; + // cout << "Acc2 " << access.addr << " " << access.call_tree_node_ptr << "\n"; (*thread_private_read_addr_to_call_tree_node_map)[access.addr] = access.call_tree_node_ptr; - //cout << "Access read succ\n"; + // cout << "Access read succ\n"; #endif #if DP_CALLTREE_PROFILING - addDep(RAW, access.lid, lastWrite, access.var, access.AAvar, - access.addr, thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map); + addDep(RAW, access.lid, lastWrite, access.var, access.AAvar, access.addr, + thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map); #else - addDep(RAW, access.lid, lastWrite, access.var, access.AAvar, - access.addr); -#endif + addDep(RAW, access.lid, lastWrite, access.var, access.AAvar, access.addr); +#endif } } else { sigElement lastWrite = SMem->insertToWrite(access.addr, access.lid); #if DP_CALLTREE_PROFILING - //cout << "Acc3 " << access.addr << " " << access.call_tree_node_ptr << "\n"; - //cout << "Acc3-0: " << write_addr_to_call_tree_node_map << "\n"; - - //cout << "Acc3-2 " << write_addr_to_call_tree_node_map << "\n"; + // cout << "Acc3 " << access.addr << " " << access.call_tree_node_ptr << "\n"; + // cout << "Acc3-0: " << write_addr_to_call_tree_node_map << "\n"; + + // cout << "Acc3-2 " << write_addr_to_call_tree_node_map << "\n"; - (*thread_private_write_addr_to_call_tree_node_map)[access.addr] = access.call_tree_node_ptr; - //cout << "Access write succ\n"; + (*thread_private_write_addr_to_call_tree_node_map)[access.addr] = access.call_tree_node_ptr; + // cout << "Access write succ\n"; #endif if (lastWrite == 0) { // INIT #if DP_CALLTREE_PROFILING - addDep(INIT, access.lid, 0, access.var, access.AAvar, - access.addr, thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map); + addDep(INIT, access.lid, 0, access.var, access.AAvar, access.addr, + thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map); #else - addDep(INIT, access.lid, 0, access.var, access.AAvar, - access.addr); -#endif + addDep(INIT, access.lid, 0, access.var, access.AAvar, access.addr); +#endif } else { sigElement lastRead = SMem->testInRead(access.addr); if (lastRead != 0) { // WAR #if DP_CALLTREE_PROFILING - addDep(WAR, access.lid, lastRead, access.var, access.AAvar, - access.addr, thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map); + addDep(WAR, access.lid, lastRead, access.var, access.AAvar, access.addr, + thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map); #else - addDep(WAR, access.lid, lastRead, access.var, access.AAvar, - access.addr); + addDep(WAR, access.lid, lastRead, access.var, access.AAvar, access.addr); #endif // Clear intermediate read ops SMem->insertToRead(access.addr, 0); #if DP_CALLTREE_PROFILING - //cout << "Acc4 " << access.addr << " " << access.call_tree_node_ptr << "\n"; + // cout << "Acc4 " << access.addr << " " << access.call_tree_node_ptr << "\n"; (*thread_private_read_addr_to_call_tree_node_map)[access.addr] = access.call_tree_node_ptr; - //cout << "Access read succ\n"; + // cout << "Access read succ\n"; #endif } else { // WAW -#if DP_CALLTREE_PROFILING - addDep(WAW, access.lid, lastWrite, access.var, access.AAvar, - access.addr, thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map); +#if DP_CALLTREE_PROFILING + addDep(WAW, access.lid, lastWrite, access.var, access.AAvar, access.addr, + thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map); #else - addDep(WAW, access.lid, lastWrite, access.var, access.AAvar, - access.addr); + addDep(WAW, access.lid, lastWrite, access.var, access.AAvar, access.addr); #endif } } @@ -486,8 +499,10 @@ void *analyzeDeps(void *arg) { } myMap = new depMap(); #if DP_CALLTREE_PROFILING - std::unordered_map>* thread_private_write_addr_to_call_tree_node_map = new std::unordered_map>(); - std::unordered_map>* thread_private_read_addr_to_call_tree_node_map = new std::unordered_map>(); + std::unordered_map> *thread_private_write_addr_to_call_tree_node_map = + new std::unordered_map>(); + std::unordered_map> *thread_private_read_addr_to_call_tree_node_map = + new std::unordered_map>(); #endif bool isLocked = false; while (true) { @@ -514,7 +529,8 @@ void *analyzeDeps(void *arg) { access = accesses[i]; #if DP_CALLTREE_PROFILING - analyzeSingleAccess(SMem, access, thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map); + analyzeSingleAccess(SMem, access, thread_private_write_addr_to_call_tree_node_map, + thread_private_read_addr_to_call_tree_node_map); #else analyzeSingleAccess(SMem, access); #endif @@ -593,9 +609,8 @@ void finalizeParallelization() { for (int i = 0; i < NUM_WORKERS; ++i) pthread_join(workers[i], NULL); - #if DP_CALLTREE_PROFILING - //metadata_queue->blocking_finalize_queue(); + // metadata_queue->blocking_finalize_queue(); #endif // destroy mutexes and condition variables diff --git a/rtlib/runtimeFunctions.hpp b/rtlib/runtimeFunctions.hpp index 7a7502191..ed60bccb6 100644 --- a/rtlib/runtimeFunctions.hpp +++ b/rtlib/runtimeFunctions.hpp @@ -13,8 +13,8 @@ #pragma once #include "DPTypes.hpp" -#include "runtimeFunctionsTypes.hpp" #include "memory/AbstractShadow.hpp" +#include "runtimeFunctionsTypes.hpp" #include diff --git a/rtlib/runtimeFunctionsGlobals.cpp b/rtlib/runtimeFunctionsGlobals.cpp index 45c9e47d4..8b736ea43 100644 --- a/rtlib/runtimeFunctionsGlobals.cpp +++ b/rtlib/runtimeFunctionsGlobals.cpp @@ -33,9 +33,9 @@ FunctionManager *function_manager = nullptr; LoopManager *loop_manager = nullptr; MemoryManager *memory_manager = nullptr; CallTree *call_tree = nullptr; -//MetaDataQueue *metadata_queue = nullptr; -std::mutex* dependency_metadata_results_mtx = nullptr; -std::unordered_set* dependency_metadata_results = nullptr; +// MetaDataQueue *metadata_queue = nullptr; +std::mutex *dependency_metadata_results_mtx = nullptr; +std::unordered_set *dependency_metadata_results = nullptr; // hybrid analysis ReportedBBSet *bbList = nullptr; diff --git a/rtlib/runtimeFunctionsGlobals.hpp b/rtlib/runtimeFunctionsGlobals.hpp index 053eef44d..0da5fc242 100644 --- a/rtlib/runtimeFunctionsGlobals.hpp +++ b/rtlib/runtimeFunctionsGlobals.hpp @@ -13,10 +13,10 @@ #pragma once #include "../share/include/timer.hpp" -#include "runtimeFunctionsTypes.hpp" -#include "memory/AbstractShadow.hpp" #include "calltree/CallTree.hpp" #include "calltree/DependencyMetadata.hpp" +#include "memory/AbstractShadow.hpp" +#include "runtimeFunctionsTypes.hpp" #include @@ -52,9 +52,9 @@ extern FunctionManager *function_manager; extern LoopManager *loop_manager; extern MemoryManager *memory_manager; extern CallTree *call_tree; -//extern MetaDataQueue * metadata_queue; -extern std::mutex* dependency_metadata_results_mtx; -extern std::unordered_set* dependency_metadata_results; +// extern MetaDataQueue * metadata_queue; +extern std::mutex *dependency_metadata_results_mtx; +extern std::unordered_set *dependency_metadata_results; // hybrid analysis extern ReportedBBSet *bbList; diff --git a/rtlib/runtimeFunctionsTypes.hpp b/rtlib/runtimeFunctionsTypes.hpp index f0e0b0511..6b8d2a962 100644 --- a/rtlib/runtimeFunctionsTypes.hpp +++ b/rtlib/runtimeFunctionsTypes.hpp @@ -60,13 +60,13 @@ struct AccessInfo { AccessInfo(bool isRead, LID lid, char *var, std::string AAvar, ADDR addr, bool skip = false) : isRead(isRead), lid(lid), var(var), AAvar(AAvar), addr(addr), skip(skip) { #if DP_CALLTREE_PROFILING - call_tree_node_ptr = nullptr; + call_tree_node_ptr = nullptr; #endif - } + } AccessInfo() : isRead(false), lid(0), var(""), AAvar(""), addr(0), skip(false) { #if DP_CALLTREE_PROFILING - call_tree_node_ptr = nullptr; + call_tree_node_ptr = nullptr; #endif } @@ -85,8 +85,7 @@ struct AccessInfo { // For runtime dependency merging struct Dep { - Dep(depType T, LID dep, const char *var, std::string AAvar) - : type(T), depOn(dep), var(var), AAvar(AAvar) {} + Dep(depType T, LID dep, const char *var, std::string AAvar) : type(T), depOn(dep), var(var), AAvar(AAvar) {} depType type; LID depOn; diff --git a/share/include/timer.hpp b/share/include/timer.hpp index 416aa1331..124cc981c 100644 --- a/share/include/timer.hpp +++ b/share/include/timer.hpp @@ -12,14 +12,14 @@ #pragma once +#include #include #include #include -#include #include +#include #include #include -#include /** * This type allows type-safe specification of a specific timer @@ -223,14 +223,15 @@ class Timers { stream << "\n========== DiscoPoP TIMERS: calltree profiling ======\n"; print(stream, " Context: Analyze singe accesses : ", TimerRegion::ANALYZE_SINGLE_ACCESS); print(stream, " |- Context: Add a dependency : ", TimerRegion::ADD_DEP); - print(stream, " |- Register MetaDataQueueElements : ", TimerRegion::ADD_DEP_CALLTREE_REGISTER_METADATAQUEUEELEMENT); + print(stream, " |- Register MetaDataQueueElements : ", + TimerRegion::ADD_DEP_CALLTREE_REGISTER_METADATAQUEUEELEMENT); print(stream, " MetaDataQueue: processQueue : ", TimerRegion::METADATAQUEUE_PROCESSQUEUE); print(stream, " |- Fetch MetaDataQueueElement : ", TimerRegion::METADATAQUEUE_PROCESSQUEUE_FETCH); - print(stream, " |- processQueueElement : ", TimerRegion::METADATAQUEUE_PROCESSQUEUEELEMENT); + print(stream, + " |- processQueueElement : ", TimerRegion::METADATAQUEUE_PROCESSQUEUEELEMENT); print(stream, " Stand-alone processQueueElement : ", TimerRegion::PROCESSQUEUEELEMENT); stream << "\n"; #endif - } /** diff --git a/test/end_to_end/do_all/calls/complex/src/code.cpp b/test/end_to_end/do_all/calls/complex/src/code.cpp index 8572d56c4..96b0e1534 100644 --- a/test/end_to_end/do_all/calls/complex/src/code.cpp +++ b/test/end_to_end/do_all/calls/complex/src/code.cpp @@ -1,40 +1,34 @@ -#include #include +#include -void perform_calculation(double* base, int offset_1, int offset_2){ - base[offset_1] = 42 + base[offset_2]; -} +void perform_calculation(double *base, int offset_1, int offset_2) { base[offset_1] = 42 + base[offset_2]; } -void doall_possible(double* base, int index){ - perform_calculation(base, index, index); -} +void doall_possible(double *base, int index) { perform_calculation(base, index, index); } -void doall_not_possible(double* base, int index, int n){ - perform_calculation(base, index, (index + 422 % n)); -} +void doall_not_possible(double *base, int index, int n) { perform_calculation(base, index, (index + 422 % n)); } -int main(int argc, const char* argv[]) { - static int n = 5000; static double a = 2.0; //n = 100000000; - double *x = (double *) malloc(n * sizeof(double)); - // Initialize x - - // DOALL - for(int i = 0; i < n; ++i){ - x[i] = 1.0; - } - - // DOALL - for(int i = 0; i < n; i++){ - doall_possible(x, i); - } - - // NOT DOALL - for(int i = 0; i < n; i++){ - doall_not_possible(x, i, n); - } - - - free(x);; -return 0; -} +int main(int argc, const char *argv[]) { + static int n = 5000; + static double a = 2.0; // n = 100000000; + double *x = (double *)malloc(n * sizeof(double)); + // Initialize x + + // DOALL + for (int i = 0; i < n; ++i) { + x[i] = 1.0; + } + + // DOALL + for (int i = 0; i < n; i++) { + doall_possible(x, i); + } + // NOT DOALL + for (int i = 0; i < n; i++) { + doall_not_possible(x, i, n); + } + + free(x); + ; + return 0; +} diff --git a/test/end_to_end/do_all/calls/complex/test.py b/test/end_to_end/do_all/calls/complex/test.py index bf9a93d01..6a3bd68d2 100644 --- a/test/end_to_end/do_all/calls/complex/test.py +++ b/test/end_to_end/do_all/calls/complex/test.py @@ -67,7 +67,7 @@ def test(self): for pattern_type in self.test_output.patterns.__dict__: amount_of_identified_patterns = len(self.test_output.patterns.__dict__[pattern_type]) if pattern_type == "do_all": - expected_lines = ["1:22", "1:27"] + expected_lines = ["1:17", "1:22"] with self.subTest("check for FP"): res, msg = check_patterns_for_FP(self, pattern_type, copy.deepcopy(expected_lines), self.test_output.patterns.__dict__[pattern_type]) self.assertTrue(res, msg) diff --git a/test/end_to_end/do_all/calls/complex_no_varname_duplicates/src/code.cpp b/test/end_to_end/do_all/calls/complex_no_varname_duplicates/src/code.cpp index 299195a8f..151c69d6c 100644 --- a/test/end_to_end/do_all/calls/complex_no_varname_duplicates/src/code.cpp +++ b/test/end_to_end/do_all/calls/complex_no_varname_duplicates/src/code.cpp @@ -1,40 +1,36 @@ -#include #include +#include -void perform_calculation(double* base_1, int offset_1, int offset_2){ - base_1[offset_1] = 42 + base_1[offset_2]; -} +void perform_calculation(double *base_1, int offset_1, int offset_2) { base_1[offset_1] = 42 + base_1[offset_2]; } -void doall_possible(double* base_2, int index_2){ - perform_calculation(base_2, index_2, index_2); -} +void doall_possible(double *base_2, int index_2) { perform_calculation(base_2, index_2, index_2); } -void doall_not_possible(double* base_3, int index_3, int n_3){ - perform_calculation(base_3, index_3, (index_3 + 422 % n_3)); +void doall_not_possible(double *base_3, int index_3, int n_3) { + perform_calculation(base_3, index_3, (index_3 + 422 % n_3)); } -int main(int argc, const char* argv[]) { - static int n = 5000; static double a = 2.0; //n = 100000000; - double *x = (double *) malloc(n * sizeof(double)); - // Initialize x - - // DOALL - for(int i = 0; i < n; ++i){ - x[i] = 1.0; - } - - // DOALL - for(int i = 0; i < n; i++){ - doall_possible(x, i); - } - - // NOT DOALL - for(int i = 0; i < n; i++){ - doall_not_possible(x, i, n); - } - - - free(x);; -return 0; -} +int main(int argc, const char *argv[]) { + static int n = 5000; + static double a = 2.0; // n = 100000000; + double *x = (double *)malloc(n * sizeof(double)); + // Initialize x + // DOALL + for (int i = 0; i < n; ++i) { + x[i] = 1.0; + } + + // DOALL + for (int i = 0; i < n; i++) { + doall_possible(x, i); + } + + // NOT DOALL + for (int i = 0; i < n; i++) { + doall_not_possible(x, i, n); + } + + free(x); + ; + return 0; +} diff --git a/test/end_to_end/do_all/calls/complex_no_varname_duplicates/test.py b/test/end_to_end/do_all/calls/complex_no_varname_duplicates/test.py index bc7d22eb0..e32490be4 100644 --- a/test/end_to_end/do_all/calls/complex_no_varname_duplicates/test.py +++ b/test/end_to_end/do_all/calls/complex_no_varname_duplicates/test.py @@ -66,7 +66,7 @@ def validate_results(self, test_dir, src_dir): for pattern_type in test_output.patterns.__dict__: amount_of_identified_patterns = len(test_output.patterns.__dict__[pattern_type]) if pattern_type == "do_all": - expected = ["1:22", "1:27"] + expected = ["1:19", "1:24"] for pattern in test_output.patterns.__dict__[pattern_type]: self.assertTrue(pattern.start_line in expected, "False positive: Pattern at " + pattern.start_line + " not in expected result: " + str(expected)) self.assertTrue(len(test_output.patterns.__dict__[pattern_type]) == 2, "False negative: Missed pattern. \nFound: " + " ".join([p.start_line for p in test_output.patterns.__dict__[pattern_type]])+"\nExpected: " + " ".join(expected)) diff --git a/test/end_to_end/do_all/simple/nested/depth_2/positive/both_loops_doall/src/FileMapping.txt b/test/end_to_end/do_all/simple/nested/depth_2/positive/both_loops_doall/src/FileMapping.txt new file mode 100644 index 000000000..98c374b83 --- /dev/null +++ b/test/end_to_end/do_all/simple/nested/depth_2/positive/both_loops_doall/src/FileMapping.txt @@ -0,0 +1 @@ +1 /home/lukas/git/discopop/test/end_to_end/do_all/simple/nested/depth_2/positive/both_loops_doall/src/code.cpp diff --git a/test/unit_tests/calltree/call_tree/test_call_tree.cpp b/test/unit_tests/calltree/call_tree/test_call_tree.cpp index f53102162..d67663e4a 100644 --- a/test/unit_tests/calltree/call_tree/test_call_tree.cpp +++ b/test/unit_tests/calltree/call_tree/test_call_tree.cpp @@ -49,7 +49,7 @@ TEST_F(CallTreeTest, testEnterLoop) { ASSERT_EQ(ct.get_current_node_ptr()->get_loop_or_function_id(), 42); } -TEST_F(CallTreeTest, testExitLoop){ +TEST_F(CallTreeTest, testExitLoop) { auto ct = __dp::CallTree(); ct.enter_function(42); ct.enter_loop(43); @@ -58,7 +58,7 @@ TEST_F(CallTreeTest, testExitLoop){ ct.exit_loop(); ASSERT_EQ(ct.get_current_node_ptr()->get_node_type(), __dp::CallTreeNodeType::Function); - ASSERT_EQ(ct.get_current_node_ptr()->get_loop_or_function_id(), 42) ; + ASSERT_EQ(ct.get_current_node_ptr()->get_loop_or_function_id(), 42); ASSERT_EQ(ct.get_node_count(), 2); } @@ -71,7 +71,7 @@ TEST_F(CallTreeTest, testEnterFunction) { ASSERT_EQ(ct.get_current_node_ptr()->get_loop_or_function_id(), 42); } -TEST_F(CallTreeTest, testExitFunctionSimple){ +TEST_F(CallTreeTest, testExitFunctionSimple) { auto ct = __dp::CallTree(); ct.enter_function(42); ct.enter_loop(43); @@ -83,7 +83,7 @@ TEST_F(CallTreeTest, testExitFunctionSimple){ ASSERT_EQ(ct.get_node_count(), 1); } -TEST_F(CallTreeTest, testExitFunction){ +TEST_F(CallTreeTest, testExitFunction) { auto ct = __dp::CallTree(); ct.enter_function(42); ct.enter_loop(43); @@ -99,7 +99,6 @@ TEST_F(CallTreeTest, testExitFunction){ ASSERT_EQ(ct.get_node_count(), 1); } - TEST_F(CallTreeTest, testEnterIterations) { auto ct = __dp::CallTree(); ct.enter_loop(42); @@ -122,7 +121,7 @@ TEST_F(CallTreeTest, testEnterIterations) { ASSERT_EQ(ct.get_current_node_ptr()->get_iteration_id(), 2); } -TEST_F(CallTreeTest, testAutomaticCleanup){ +TEST_F(CallTreeTest, testAutomaticCleanup) { auto ct = __dp::CallTree(); ct.enter_function(42); ct.enter_loop(43); @@ -134,17 +133,17 @@ TEST_F(CallTreeTest, testAutomaticCleanup){ ASSERT_EQ(ct.get_node_count(), 4); } -TEST_F(CallTreeTest, testPreventAutomaticCleanup){ +TEST_F(CallTreeTest, testPreventAutomaticCleanup) { auto ct = __dp::CallTree(); ct.enter_function(42); ct.enter_loop(43); ct.enter_iteration(1); ASSERT_EQ(ct.get_node_count(), 4); - + { // save ptr to iteration 1 to prevent cleanup std::shared_ptr<__dp::CallTreeNode> dummy_ptr = ct.get_current_node_ptr(); - + ct.enter_iteration(2); // iteration node 1 shall NOT be deleted, since a referenced still exists ASSERT_EQ(ct.get_node_count(), 5); @@ -154,7 +153,7 @@ TEST_F(CallTreeTest, testPreventAutomaticCleanup){ ASSERT_EQ(ct.get_node_count(), 4); } -TEST_F(CallTreeTest, testImmediateFuncExit){ +TEST_F(CallTreeTest, testImmediateFuncExit) { auto ct = __dp::CallTree(); ct.exit_function(); // check for segfaults diff --git a/test/unit_tests/calltree/call_tree_node/test_call_tree_node.cpp b/test/unit_tests/calltree/call_tree_node/test_call_tree_node.cpp index aa118eb88..ef6b2cb54 100644 --- a/test/unit_tests/calltree/call_tree_node/test_call_tree_node.cpp +++ b/test/unit_tests/calltree/call_tree_node/test_call_tree_node.cpp @@ -6,15 +6,15 @@ class CallTreeNodeTest : public ::testing::Test {}; TEST_F(CallTreeNodeTest, testConstructor) { - auto ctn = __dp::CallTreeNode( nullptr, __dp::CallTreeNodeType::Function, 1, 0); - + auto ctn = __dp::CallTreeNode(nullptr, __dp::CallTreeNodeType::Function, 1, 0); + ASSERT_EQ(ctn.get_loop_or_function_id(), 1); ASSERT_EQ(ctn.get_node_type(), __dp::CallTreeNodeType::Function); } TEST_F(CallTreeNodeTest, testDefaultConstructor) { auto ctn = __dp::CallTreeNode(); - + ASSERT_EQ(ctn.get_loop_or_function_id(), 0); ASSERT_EQ(ctn.get_node_type(), __dp::CallTreeNodeType::Root); ASSERT_EQ(ctn.get_iteration_id(), 0); @@ -22,47 +22,47 @@ TEST_F(CallTreeNodeTest, testDefaultConstructor) { } TEST_F(CallTreeNodeTest, testGetIterationId) { - auto ctn = __dp::CallTreeNode( nullptr, __dp::CallTreeNodeType::Root, 0, 0); + auto ctn = __dp::CallTreeNode(nullptr, __dp::CallTreeNodeType::Root, 0, 0); ASSERT_EQ(ctn.get_loop_or_function_id(), 0); ASSERT_EQ(ctn.get_node_type(), __dp::CallTreeNodeType::Root); ASSERT_EQ(ctn.get_iteration_id(), 0); - ctn = __dp::CallTreeNode( nullptr, __dp::CallTreeNodeType::Root, 0, 1); + ctn = __dp::CallTreeNode(nullptr, __dp::CallTreeNodeType::Root, 0, 1); ASSERT_EQ(ctn.get_loop_or_function_id(), 0); ASSERT_EQ(ctn.get_node_type(), __dp::CallTreeNodeType::Root); ASSERT_EQ(ctn.get_iteration_id(), 0); - ctn = __dp::CallTreeNode( nullptr, __dp::CallTreeNodeType::Function, 1, 0); + ctn = __dp::CallTreeNode(nullptr, __dp::CallTreeNodeType::Function, 1, 0); ASSERT_EQ(ctn.get_loop_or_function_id(), 1); ASSERT_EQ(ctn.get_node_type(), __dp::CallTreeNodeType::Function); ASSERT_EQ(ctn.get_iteration_id(), 0); - ctn = __dp::CallTreeNode( nullptr, __dp::CallTreeNodeType::Function, 1, 1); + ctn = __dp::CallTreeNode(nullptr, __dp::CallTreeNodeType::Function, 1, 1); ASSERT_EQ(ctn.get_loop_or_function_id(), 1); ASSERT_EQ(ctn.get_node_type(), __dp::CallTreeNodeType::Function); ASSERT_EQ(ctn.get_iteration_id(), 0); - ctn = __dp::CallTreeNode( nullptr, __dp::CallTreeNodeType::Loop, 2, 0); + ctn = __dp::CallTreeNode(nullptr, __dp::CallTreeNodeType::Loop, 2, 0); ASSERT_EQ(ctn.get_loop_or_function_id(), 2); ASSERT_EQ(ctn.get_node_type(), __dp::CallTreeNodeType::Loop); ASSERT_EQ(ctn.get_iteration_id(), 0); - ctn = __dp::CallTreeNode( nullptr, __dp::CallTreeNodeType::Loop, 2, 1); + ctn = __dp::CallTreeNode(nullptr, __dp::CallTreeNodeType::Loop, 2, 1); ASSERT_EQ(ctn.get_loop_or_function_id(), 2); ASSERT_EQ(ctn.get_node_type(), __dp::CallTreeNodeType::Loop); ASSERT_EQ(ctn.get_iteration_id(), 0); - ctn = __dp::CallTreeNode( nullptr, __dp::CallTreeNodeType::Iteration, 2, 1); + ctn = __dp::CallTreeNode(nullptr, __dp::CallTreeNodeType::Iteration, 2, 1); ASSERT_EQ(ctn.get_loop_or_function_id(), 2); ASSERT_EQ(ctn.get_node_type(), __dp::CallTreeNodeType::Iteration); ASSERT_EQ(ctn.get_iteration_id(), 1); } -TEST_F(CallTreeNodeTest, testGetParentPtr){ +TEST_F(CallTreeNodeTest, testGetParentPtr) { auto root = __dp::CallTreeNode(); - auto function = __dp::CallTreeNode( make_shared<__dp::CallTreeNode>(root), __dp::CallTreeNodeType::Function, 1, 0); - auto loop = __dp::CallTreeNode( make_shared<__dp::CallTreeNode>(function), __dp::CallTreeNodeType::Loop, 2, 0); - auto iteration = __dp::CallTreeNode( make_shared<__dp::CallTreeNode>(loop), __dp::CallTreeNodeType::Iteration, 2, 1); + auto function = __dp::CallTreeNode(make_shared<__dp::CallTreeNode>(root), __dp::CallTreeNodeType::Function, 1, 0); + auto loop = __dp::CallTreeNode(make_shared<__dp::CallTreeNode>(function), __dp::CallTreeNodeType::Loop, 2, 0); + auto iteration = __dp::CallTreeNode(make_shared<__dp::CallTreeNode>(loop), __dp::CallTreeNodeType::Iteration, 2, 1); ASSERT_EQ(iteration.get_parent_ptr()->get_node_type(), __dp::CallTreeNodeType::Loop); ASSERT_EQ(iteration.get_parent_ptr()->get_loop_or_function_id(), 2); diff --git a/test/unit_tests/calltree/metadata_queue/test_metadata_queue.cpp b/test/unit_tests/calltree/metadata_queue/test_metadata_queue.cpp index 1fd46b5ee..b26cc8fbc 100644 --- a/test/unit_tests/calltree/metadata_queue/test_metadata_queue.cpp +++ b/test/unit_tests/calltree/metadata_queue/test_metadata_queue.cpp @@ -4,5 +4,4 @@ class MetaDataQueueTest : public ::testing::Test {}; -TEST_F(MetaDataQueueTest, dummy) { -} \ No newline at end of file +TEST_F(MetaDataQueueTest, dummy) {} \ No newline at end of file From 25ba6735554ee5f9426f1007604657ef6a8b54b9 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Mon, 8 Jul 2024 13:47:44 +0200 Subject: [PATCH 007/105] enable compilation of benchmark suite --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 809bed8a7..fcbfe25b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,7 +70,7 @@ add_subdirectory(scripts) add_subdirectory(test/unit_tests) -#add_subdirectory(benchmark) +add_subdirectory(benchmark) ##### DEPRECATED ##### # save build configuration to build/build_config.txt From 338ffe50e577cb05f6bbd3d14278ab1976f9030c Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Mon, 8 Jul 2024 13:54:01 +0200 Subject: [PATCH 008/105] use improved data structure PerfectShadow_2 --- rtlib/runtimeFunctions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtlib/runtimeFunctions.cpp b/rtlib/runtimeFunctions.cpp index 0ee7de481..449123224 100644 --- a/rtlib/runtimeFunctions.cpp +++ b/rtlib/runtimeFunctions.cpp @@ -493,7 +493,7 @@ void *analyzeDeps(void *arg) { int64_t id = (int64_t)arg; AbstractShadow *SMem; if (USE_PERFECT) { - SMem = new PerfectShadow(SIG_ELEM_BIT, SIG_NUM_ELEM, SIG_NUM_HASH); + SMem = new PerfectShadow2(); } else { SMem = new ShadowMemory(SIG_ELEM_BIT, SIG_NUM_ELEM, SIG_NUM_HASH); } From 119fed06e8e69f4319b7ca6d76792c7a1ceea407 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Mon, 8 Jul 2024 14:31:55 +0200 Subject: [PATCH 009/105] minor optimization --- rtlib/calltree/utils.cpp | 2 +- rtlib/calltree/utils.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rtlib/calltree/utils.cpp b/rtlib/calltree/utils.cpp index 863607fde..b4f2924a9 100644 --- a/rtlib/calltree/utils.cpp +++ b/rtlib/calltree/utils.cpp @@ -17,7 +17,7 @@ namespace __dp { -DependencyMetadata processQueueElement(MetaDataQueueElement mdqe) { +DependencyMetadata processQueueElement(MetaDataQueueElement && mdqe) { const auto calltree_timer = Timer(timers, TimerRegion::PROCESSQUEUEELEMENT); // cout << "processing " << mdqe.toString() << "\n"; diff --git a/rtlib/calltree/utils.hpp b/rtlib/calltree/utils.hpp index e823db615..809190cf2 100644 --- a/rtlib/calltree/utils.hpp +++ b/rtlib/calltree/utils.hpp @@ -14,5 +14,5 @@ #include "MetaDataQueueElement.hpp" namespace __dp { -DependencyMetadata processQueueElement(MetaDataQueueElement mdqe); +DependencyMetadata processQueueElement(MetaDataQueueElement && mdqe); } // namespace __dp From 46735820bb3ea97717094a1ac2db92d392e95c90 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 9 Jul 2024 14:03:21 +0200 Subject: [PATCH 010/105] Lossy metadata calculation: loop iteration threshold --- .github/workflows/ci.yml | 1 + .../DependencyMetadata/compare_metadata.py | 49 +++++++ docs/setup/discopop.md | 1 + rtlib/CMakeLists.txt | 7 + rtlib/injected_functions/dp_read.cpp | 1 + rtlib/injected_functions/dp_write.cpp | 1 + rtlib/loop/LoopManager.hpp | 24 ++++ rtlib/loop/LoopTable.hpp | 2 + rtlib/loop/LoopTableEntry.hpp | 19 ++- rtlib/runtimeFunctions.cpp | 124 +++++++++--------- rtlib/runtimeFunctionsTypes.hpp | 3 + 11 files changed, 170 insertions(+), 62 deletions(-) create mode 100644 discopop_library/DependencyMetadata/compare_metadata.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a1227385f..c3a15ba37 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -152,6 +152,7 @@ jobs: cmake \ -DCMAKE_BUILD_TYPE=Debug \ -DDP_CALLTREE_PROFILING=1 \ + -DDP_CALLTREE_PROFILING_METADATA_CUTOFF=0 \ .. make -j3 diff --git a/discopop_library/DependencyMetadata/compare_metadata.py b/discopop_library/DependencyMetadata/compare_metadata.py new file mode 100644 index 000000000..4bc4dc927 --- /dev/null +++ b/discopop_library/DependencyMetadata/compare_metadata.py @@ -0,0 +1,49 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from typing import Set + + +def main(): + gold_result_path = "/home/lukas/dependency_metadata.txt" + gold_standard: Set[str] = set() + + with open(gold_result_path, "r") as f: + for line in f.readlines(): + line = line.replace("\n", "") + if line.startswith("#"): + continue + gold_standard.add(line) + + tested_result_path = "/home/lukas/git/Benchmarks/miniFE/dp/src/.discopop/profiler/dependency_metadata.txt" + test_results: Set[str] = set() + + with open(tested_result_path, "r") as f: + for line in f.readlines(): + line = line.replace("\n", "") + if line.startswith("#"): + continue + test_results.add(line) + + print("Total gold standard: ", len(gold_standard)) + print("Total test results: ", len(test_results)) + # identify number of matching results + matching = gold_standard.intersection(test_results) + print("Matching: ", len(matching)) + + # identify number of missed results + missed = gold_standard.difference(test_results) + print("Missed: ", len(missed)) + + # identify number of additional results + additional = test_results.difference(gold_standard) + print("Additional: ", len(additional)) + + +if __name__ == "__main__": + main() diff --git a/docs/setup/discopop.md b/docs/setup/discopop.md index c9f93f0af..3f3f9bd0a 100644 --- a/docs/setup/discopop.md +++ b/docs/setup/discopop.md @@ -34,6 +34,7 @@ where `` can consist of any combination of the following flags and - `-DDP_NUM_WORKERS=` – Specify the number of worker threads available for the dependency analysis during profiling. Default: `3` worker threads. `0` can be used to disable the creation of additional threads for the analysis. - `-DDP_HYBRID_PROFILING=[0|1]` – Enbale hybrid profiling. Default: `1`. - `-DDP_CALLTREE_PROFILING=[0|1]` – Enable creation of a call tree during profiling to create extended dependency metadata for improved result quality. Negatively impacts profiling performance. +- `-DDP_CALLTREE_PROFILING_METADATA_CUTOFF=` – Set a cutoff amount of vitis per basic block for dependency metadata calculation. Set `0` to disable cutoff. Default: `50000`. - `-DDP_MEMORY_REGION_DEALIASING=[0|1]`: Enable or disable the generation of dependency de-aliasing information. Reduces potential false positive parallelization suggestions, but increases the profiling overhead. diff --git a/rtlib/CMakeLists.txt b/rtlib/CMakeLists.txt index 2d901e4d3..4d1954af1 100644 --- a/rtlib/CMakeLists.txt +++ b/rtlib/CMakeLists.txt @@ -86,6 +86,13 @@ if(DEFINED DP_CALLTREE_PROFILING) endif() endif() +if(DEFINED DP_CALLTREE_PROFILING_METADATA_CUTOFF) + target_compile_definitions(DiscoPoP_RT PUBLIC DP_CALLTREE_PROFILING_METADATA_CUTOFF=${DP_CALLTREE_PROFILING_METADATA_CUTOFF}) + message(STATUS "WARNING: DiscoPoP configuration: DP_CALLTREE_PROFILING_METADATA_CUTOFF enabled. Incomplete dependency metadata possible.") +else() + target_compile_definitions(DiscoPoP_RT PUBLIC DP_CALLTREE_PROFILING_METADATA_CUTOFF=50) + message(STATUS "WARNING: DiscoPoP configuration: DP_CALLTREE_PROFILING_METADATA_CUTOFF set to default value: 50.") +endif() if(DEFINED DP_MEMORY_REGION_DEALIASING) if(NOT ${DP_MEMORY_REGION_DEALIASING} EQUAL 0) diff --git a/rtlib/injected_functions/dp_read.cpp b/rtlib/injected_functions/dp_read.cpp index 53edae075..8538666b9 100644 --- a/rtlib/injected_functions/dp_read.cpp +++ b/rtlib/injected_functions/dp_read.cpp @@ -92,6 +92,7 @@ void __dp_read(LID lid, ADDR addr, const char *var) { current.addr = addr; #if DP_CALLTREE_PROFILING current.call_tree_node_ptr = call_tree->get_current_node_ptr(); + current.calculate_dependency_metadata = loop_manager->enable_calculate_dependency_metadata(); #endif #if defined DP_NUM_WORKERS && DP_NUM_WORKERS == 0 diff --git a/rtlib/injected_functions/dp_write.cpp b/rtlib/injected_functions/dp_write.cpp index f4d7a825e..d0c8863be 100644 --- a/rtlib/injected_functions/dp_write.cpp +++ b/rtlib/injected_functions/dp_write.cpp @@ -95,6 +95,7 @@ void __dp_write(LID lid, ADDR addr, const char *var) { #if DP_CALLTREE_PROFILING current.call_tree_node_ptr = call_tree->get_current_node_ptr(); + current.calculate_dependency_metadata = loop_manager->enable_calculate_dependency_metadata(); #endif #if defined DP_NUM_WORKERS && DP_NUM_WORKERS == 0 diff --git a/rtlib/loop/LoopManager.hpp b/rtlib/loop/LoopManager.hpp index bc62372d0..44778389f 100644 --- a/rtlib/loop/LoopManager.hpp +++ b/rtlib/loop/LoopManager.hpp @@ -33,7 +33,20 @@ class LoopManager { } void create_new_loop(const std::int32_t function_level, const std::int32_t loop_id, const LID begin_line) { +#if DP_CALLTREE_PROFILING + // check if dependency metadata calculation should be disabled due to inheritance + bool inherited_dep_metadata_calculation = true; + if (! loopStack.empty()){ + inherited_dep_metadata_calculation = loopStack.top().get_dependency_metadata_calculation_enabled(); + } + +#endif loopStack.push(LoopTableEntry(function_level, loop_id, 0, begin_line)); +#if DP_CALLTREE_PROFILING + // set the inherited metadata calculation flag + loopStack.non_const_top().set_dependency_metadata_calculation_enabled(inherited_dep_metadata_calculation); + +#endif if (loops.find(begin_line) == loops.end()) { loops.insert(pair(begin_line, new LoopRecord(0, 0, 0))); } @@ -46,8 +59,19 @@ class LoopManager { return loopStack.empty() || (loopStack.top().loopID != loop_id); } +#if DP_CALLTREE_PROFILING + bool enable_calculate_dependency_metadata() { + return loopStack.top().get_dependency_metadata_calculation_enabled(); + }; +#endif + void iterate_loop(const std::int32_t function_level) { loopStack.increment_top_count(); +#if DP_CALLTREE_PROFILING + if(! DP_CALLTREE_PROFILING_METADATA_CUTOFF == 0){ + loopStack.non_const_top().set_dependency_metadata_calculation_enabled(loopStack.top().get_dependency_metadata_calculation_enabled() && (DP_CALLTREE_PROFILING_METADATA_CUTOFF > loopStack.top().get_count())); + } +#endif #ifdef DP_DEBUG std::cout << "(" << std::dec << loopStack.top().funcLevel << ")"; std::cout << "Loop " << loopStack.top().loopID << " iterates " << loopStack.top().count << " times." << std::endl; diff --git a/rtlib/loop/LoopTable.hpp b/rtlib/loop/LoopTable.hpp index 00070ebc8..61dddc11a 100644 --- a/rtlib/loop/LoopTable.hpp +++ b/rtlib/loop/LoopTable.hpp @@ -26,6 +26,8 @@ struct LoopTable { const LoopTableEntry &top() const { return contents.back(); } + LoopTableEntry &non_const_top() { return contents.back(); } + const LoopTableEntry &first() const { return contents[0]; } const LoopTableEntry &topMinusN(const std::size_t n) const { return contents[contents.size() - 1 - n]; } diff --git a/rtlib/loop/LoopTableEntry.hpp b/rtlib/loop/LoopTableEntry.hpp index 022393df1..a32e4ba41 100644 --- a/rtlib/loop/LoopTableEntry.hpp +++ b/rtlib/loop/LoopTableEntry.hpp @@ -21,7 +21,11 @@ namespace __dp { // For loop tracking struct LoopTableEntry { LoopTableEntry(std::int32_t function_level, std::int32_t loop_id, std::int32_t number_hits, LID begin_line) - : funcLevel(function_level), loopID(loop_id), count(number_hits), begin(begin_line) {} + : funcLevel(function_level), loopID(loop_id), count(number_hits), begin(begin_line) { +#if DP_CALLTREE_PROFILING + dependency_metadata_calculation_enabled = true; +#endif + } std::int32_t funcLevel; std::int32_t loopID; @@ -37,8 +41,21 @@ struct LoopTableEntry { void increment_count() noexcept { ++count; } +#if DP_CALLTREE_PROFILING + void set_dependency_metadata_calculation_enabled(bool value){ + dependency_metadata_calculation_enabled = value; + } + + bool get_dependency_metadata_calculation_enabled() const { + return dependency_metadata_calculation_enabled; + } +#endif + private: std::int32_t count; +#if DP_CALLTREE_PROFILING + bool dependency_metadata_calculation_enabled; +#endif }; } // namespace __dp diff --git a/rtlib/runtimeFunctions.cpp b/rtlib/runtimeFunctions.cpp index 449123224..462c9799e 100644 --- a/rtlib/runtimeFunctions.cpp +++ b/rtlib/runtimeFunctions.cpp @@ -59,7 +59,7 @@ namespace __dp { #if DP_CALLTREE_PROFILING void addDep(depType type, LID curr, LID depOn, const char *var, string AAvar, ADDR addr, std::unordered_map> *thread_private_write_addr_to_call_tree_node_map, - std::unordered_map> *thread_private_read_addr_to_call_tree_node_map) { + std::unordered_map> *thread_private_read_addr_to_call_tree_node_map, bool calculate_dependency_metadata) { #else void addDep(depType type, LID curr, LID depOn, const char *var, string AAvar, ADDR addr) { #endif @@ -91,62 +91,64 @@ void addDep(depType type, LID curr, LID depOn, const char *var, string AAvar, AD #if DP_CALLTREE_PROFILING // register dependency for call_tree based metadata calculation - DependencyMetadata dmd; - switch (type) { - case RAW: - // register metadata calculation - // cout << "Register metadata calculation: RAW " << decodeLID(curr) << " " << decodeLID(depOn) << " " << var << " (" - // << (*thread_private_write_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << - // (*thread_private_write_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ") " << " (" << - // (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << - // (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ")\n"; - - // process directly - dmd = processQueueElement(MetaDataQueueElement(type, curr, depOn, var, AAvar, - (*thread_private_read_addr_to_call_tree_node_map)[addr], - (*thread_private_write_addr_to_call_tree_node_map)[addr])); - dependency_metadata_results_mtx->lock(); - dependency_metadata_results->insert(dmd); - dependency_metadata_results_mtx->unlock(); - - // metadata_queue->insert(); // optimization potential: do not use copies here! - break; - case WAR: - // update write - // register metadata calculation - // cout << "Register metadata calculation: WAR " << decodeLID(curr) << " " << decodeLID(depOn) << " " << var << " (" - // << (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << - // (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ") " << " (" << - // (*thread_private_write_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << - // (*thread_private_write_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ")\n"; - - dmd = processQueueElement(MetaDataQueueElement(type, curr, depOn, var, AAvar, - (*thread_private_write_addr_to_call_tree_node_map)[addr], - (*thread_private_read_addr_to_call_tree_node_map)[addr])); - dependency_metadata_results_mtx->lock(); - dependency_metadata_results->insert(dmd); - dependency_metadata_results_mtx->unlock(); - // metadata_queue->insert(); // optimization potential: do not use copies here! - break; - case WAW: - // register metadata calculation - // cout << "Register metadata calculation: WAW " << decodeLID(curr) << " " << decodeLID(depOn) << " " << var << " (" - // << (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << - // (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ") " << " (" << - // (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << - // (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ")\n"; - dmd = processQueueElement(MetaDataQueueElement(type, curr, depOn, var, AAvar, - (*thread_private_write_addr_to_call_tree_node_map)[addr], - (*thread_private_write_addr_to_call_tree_node_map)[addr])); - dependency_metadata_results_mtx->lock(); - dependency_metadata_results->insert(dmd); - dependency_metadata_results_mtx->unlock(); - // metadata_queue->insert(); // optimization potential: do not use copies here! - break; - case INIT: - break; - default: - break; + if(calculate_dependency_metadata){ + DependencyMetadata dmd; + switch (type) { + case RAW: + // register metadata calculation + // cout << "Register metadata calculation: RAW " << decodeLID(curr) << " " << decodeLID(depOn) << " " << var << " (" + // << (*thread_private_write_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << + // (*thread_private_write_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ") " << " (" << + // (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << + // (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ")\n"; + + // process directly + dmd = processQueueElement(MetaDataQueueElement(type, curr, depOn, var, AAvar, + (*thread_private_read_addr_to_call_tree_node_map)[addr], + (*thread_private_write_addr_to_call_tree_node_map)[addr])); + dependency_metadata_results_mtx->lock(); + dependency_metadata_results->insert(dmd); + dependency_metadata_results_mtx->unlock(); + + // metadata_queue->insert(); // optimization potential: do not use copies here! + break; + case WAR: + // update write + // register metadata calculation + // cout << "Register metadata calculation: WAR " << decodeLID(curr) << " " << decodeLID(depOn) << " " << var << " (" + // << (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << + // (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ") " << " (" << + // (*thread_private_write_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << + // (*thread_private_write_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ")\n"; + + dmd = processQueueElement(MetaDataQueueElement(type, curr, depOn, var, AAvar, + (*thread_private_write_addr_to_call_tree_node_map)[addr], + (*thread_private_read_addr_to_call_tree_node_map)[addr])); + dependency_metadata_results_mtx->lock(); + dependency_metadata_results->insert(dmd); + dependency_metadata_results_mtx->unlock(); + // metadata_queue->insert(); // optimization potential: do not use copies here! + break; + case WAW: + // register metadata calculation + // cout << "Register metadata calculation: WAW " << decodeLID(curr) << " " << decodeLID(depOn) << " " << var << " (" + // << (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << + // (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ") " << " (" << + // (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << + // (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ")\n"; + dmd = processQueueElement(MetaDataQueueElement(type, curr, depOn, var, AAvar, + (*thread_private_write_addr_to_call_tree_node_map)[addr], + (*thread_private_write_addr_to_call_tree_node_map)[addr])); + dependency_metadata_results_mtx->lock(); + dependency_metadata_results->insert(dmd); + dependency_metadata_results_mtx->unlock(); + // metadata_queue->insert(); // optimization potential: do not use copies here! + break; + case INIT: + break; + default: + break; + } } #endif @@ -430,7 +432,7 @@ void analyzeSingleAccess(__dp::AbstractShadow *SMem, __dp::AccessInfo &access) { #endif #if DP_CALLTREE_PROFILING addDep(RAW, access.lid, lastWrite, access.var, access.AAvar, access.addr, - thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map); + thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map, access.calculate_dependency_metadata); #else addDep(RAW, access.lid, lastWrite, access.var, access.AAvar, access.addr); #endif @@ -451,7 +453,7 @@ void analyzeSingleAccess(__dp::AbstractShadow *SMem, __dp::AccessInfo &access) { // INIT #if DP_CALLTREE_PROFILING addDep(INIT, access.lid, 0, access.var, access.AAvar, access.addr, - thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map); + thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map, access.calculate_dependency_metadata); #else addDep(INIT, access.lid, 0, access.var, access.AAvar, access.addr); #endif @@ -461,7 +463,7 @@ void analyzeSingleAccess(__dp::AbstractShadow *SMem, __dp::AccessInfo &access) { // WAR #if DP_CALLTREE_PROFILING addDep(WAR, access.lid, lastRead, access.var, access.AAvar, access.addr, - thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map); + thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map, access.calculate_dependency_metadata); #else addDep(WAR, access.lid, lastRead, access.var, access.AAvar, access.addr); #endif @@ -476,7 +478,7 @@ void analyzeSingleAccess(__dp::AbstractShadow *SMem, __dp::AccessInfo &access) { // WAW #if DP_CALLTREE_PROFILING addDep(WAW, access.lid, lastWrite, access.var, access.AAvar, access.addr, - thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map); + thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map, access.calculate_dependency_metadata); #else addDep(WAW, access.lid, lastWrite, access.var, access.AAvar, access.addr); #endif diff --git a/rtlib/runtimeFunctionsTypes.hpp b/rtlib/runtimeFunctionsTypes.hpp index 6b8d2a962..9eac08518 100644 --- a/rtlib/runtimeFunctionsTypes.hpp +++ b/rtlib/runtimeFunctionsTypes.hpp @@ -61,12 +61,14 @@ struct AccessInfo { : isRead(isRead), lid(lid), var(var), AAvar(AAvar), addr(addr), skip(skip) { #if DP_CALLTREE_PROFILING call_tree_node_ptr = nullptr; + calculate_dependency_metadata = true; #endif } AccessInfo() : isRead(false), lid(0), var(""), AAvar(""), addr(0), skip(false) { #if DP_CALLTREE_PROFILING call_tree_node_ptr = nullptr; + calculate_dependency_metadata = true; #endif } @@ -80,6 +82,7 @@ struct AccessInfo { ADDR addr; #if DP_CALLTREE_PROFILING shared_ptr call_tree_node_ptr; + bool calculate_dependency_metadata; #endif }; From 7c9058a9951b0047c2d963c2b45daccb0cd00f08 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 9 Jul 2024 14:05:49 +0200 Subject: [PATCH 011/105] formatting --- discopop_library/DependencyMetadata/compare_metadata.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/discopop_library/DependencyMetadata/compare_metadata.py b/discopop_library/DependencyMetadata/compare_metadata.py index 4bc4dc927..852f28320 100644 --- a/discopop_library/DependencyMetadata/compare_metadata.py +++ b/discopop_library/DependencyMetadata/compare_metadata.py @@ -29,7 +29,7 @@ def main(): if line.startswith("#"): continue test_results.add(line) - + print("Total gold standard: ", len(gold_standard)) print("Total test results: ", len(test_results)) # identify number of matching results @@ -40,7 +40,7 @@ def main(): missed = gold_standard.difference(test_results) print("Missed: ", len(missed)) - # identify number of additional results + # identify number of additional results additional = test_results.difference(gold_standard) print("Additional: ", len(additional)) From 9e7f5335bb1a9e2077caae88cb069d79807b497b Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 9 Jul 2024 15:33:56 +0200 Subject: [PATCH 012/105] cleanup --- CMakeLists.txt | 1 + .../nested/depth_2/positive/both_loops_doall/src/FileMapping.txt | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 test/end_to_end/do_all/simple/nested/depth_2/positive/both_loops_doall/src/FileMapping.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index fcbfe25b9..855347cac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,6 +96,7 @@ file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build_config.py" "DP_NUM_WORKERS=\"${DP_NUM_WORKERS}\"\n") file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build_config.py" "DP_INTERNAL_TIMER=\"${DP_INTERNAL_TIMER}\"\n") file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build_config.py" "DP_CALLTREE_PROFILING=\"${DP_CALLTREE_PROFILING}\"\n") +file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build_config.py" "DP_CALLTREE_PROFILING_METADATA_CUTOFF=\"${DP_CALLTREE_PROFILING_METADATA_CUTOFF}\"\n") file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build_config.py" "DP_MEMORY_REGION_DEALIASING=\"${DP_MEMORY_REGION_DEALIASING}\"\n") diff --git a/test/end_to_end/do_all/simple/nested/depth_2/positive/both_loops_doall/src/FileMapping.txt b/test/end_to_end/do_all/simple/nested/depth_2/positive/both_loops_doall/src/FileMapping.txt deleted file mode 100644 index 98c374b83..000000000 --- a/test/end_to_end/do_all/simple/nested/depth_2/positive/both_loops_doall/src/FileMapping.txt +++ /dev/null @@ -1 +0,0 @@ -1 /home/lukas/git/discopop/test/end_to_end/do_all/simple/nested/depth_2/positive/both_loops_doall/src/code.cpp From e2e628bf2e934a7fe1e061c03b87d92ada272e47 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 9 Jul 2024 17:03:18 +0200 Subject: [PATCH 013/105] add probabilistic cutoff ignore --- CMakeLists.txt | 1 + docs/setup/discopop.md | 1 + rtlib/CMakeLists.txt | 10 ++++++++++ rtlib/loop/LoopManager.hpp | 5 +++++ 4 files changed, 17 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 855347cac..7931a04c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,6 +97,7 @@ file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build_config.py" "DP_INTERNAL_TIMER=\"${DP_INTERNAL_TIMER}\"\n") file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build_config.py" "DP_CALLTREE_PROFILING=\"${DP_CALLTREE_PROFILING}\"\n") file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build_config.py" "DP_CALLTREE_PROFILING_METADATA_CUTOFF=\"${DP_CALLTREE_PROFILING_METADATA_CUTOFF}\"\n") +file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build_config.py" "DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY=\"${DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY}\"\n") file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build_config.py" "DP_MEMORY_REGION_DEALIASING=\"${DP_MEMORY_REGION_DEALIASING}\"\n") diff --git a/docs/setup/discopop.md b/docs/setup/discopop.md index 3f3f9bd0a..604e72acd 100644 --- a/docs/setup/discopop.md +++ b/docs/setup/discopop.md @@ -35,6 +35,7 @@ where `` can consist of any combination of the following flags and - `-DDP_HYBRID_PROFILING=[0|1]` – Enbale hybrid profiling. Default: `1`. - `-DDP_CALLTREE_PROFILING=[0|1]` – Enable creation of a call tree during profiling to create extended dependency metadata for improved result quality. Negatively impacts profiling performance. - `-DDP_CALLTREE_PROFILING_METADATA_CUTOFF=` – Set a cutoff amount of vitis per basic block for dependency metadata calculation. Set `0` to disable cutoff. Default: `50000`. +- `-DDP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY=[0-1000]` – Enable or disable probablistic cutoff. Ignores cutoff with a configurable probability. Set `0` to disable probabilistic cutoff. Set `25` for a probability of 2.5% etc. - `-DDP_MEMORY_REGION_DEALIASING=[0|1]`: Enable or disable the generation of dependency de-aliasing information. Reduces potential false positive parallelization suggestions, but increases the profiling overhead. diff --git a/rtlib/CMakeLists.txt b/rtlib/CMakeLists.txt index 4d1954af1..13157a0c8 100644 --- a/rtlib/CMakeLists.txt +++ b/rtlib/CMakeLists.txt @@ -94,6 +94,16 @@ else() message(STATUS "WARNING: DiscoPoP configuration: DP_CALLTREE_PROFILING_METADATA_CUTOFF set to default value: 50.") endif() +if(DEFINED DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY) + target_compile_definitions(DiscoPoP_RT PUBLIC DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY=${DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY}) + message(STATUS "WARNING: DiscoPoP configuration: DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY set to ${DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY}%.") +else() + target_compile_definitions(DiscoPoP_RT PUBLIC DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY=5) + message(STATUS "WARNING: DiscoPoP configuration: DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY set to default value: 5.") +endif() + + + if(DEFINED DP_MEMORY_REGION_DEALIASING) if(NOT ${DP_MEMORY_REGION_DEALIASING} EQUAL 0) target_compile_definitions(DiscoPoP_RT PUBLIC DP_MEMORY_REGION_DEALIASING=${DP_MEMORY_REGION_DEALIASING}) diff --git a/rtlib/loop/LoopManager.hpp b/rtlib/loop/LoopManager.hpp index 44778389f..dd4cc176a 100644 --- a/rtlib/loop/LoopManager.hpp +++ b/rtlib/loop/LoopManager.hpp @@ -69,7 +69,12 @@ class LoopManager { loopStack.increment_top_count(); #if DP_CALLTREE_PROFILING if(! DP_CALLTREE_PROFILING_METADATA_CUTOFF == 0){ +#if DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY + loopStack.non_const_top().set_dependency_metadata_calculation_enabled((loopStack.top().get_dependency_metadata_calculation_enabled() && (DP_CALLTREE_PROFILING_METADATA_CUTOFF > loopStack.top().get_count())) || ((rand() % 1000) < DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY)); +#else + // DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY is 0 loopStack.non_const_top().set_dependency_metadata_calculation_enabled(loopStack.top().get_dependency_metadata_calculation_enabled() && (DP_CALLTREE_PROFILING_METADATA_CUTOFF > loopStack.top().get_count())); +#endif } #endif #ifdef DP_DEBUG From 79b58f0ee6000396ce5468b0137fee9ca0ab0762 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 9 Jul 2024 17:04:52 +0200 Subject: [PATCH 014/105] improved default values --- rtlib/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rtlib/CMakeLists.txt b/rtlib/CMakeLists.txt index 13157a0c8..e8f88b431 100644 --- a/rtlib/CMakeLists.txt +++ b/rtlib/CMakeLists.txt @@ -96,10 +96,10 @@ endif() if(DEFINED DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY) target_compile_definitions(DiscoPoP_RT PUBLIC DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY=${DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY}) - message(STATUS "WARNING: DiscoPoP configuration: DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY set to ${DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY}%.") + message(STATUS "WARNING: DiscoPoP configuration: DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY set to ${DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY} * 0.1% .") else() - target_compile_definitions(DiscoPoP_RT PUBLIC DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY=5) - message(STATUS "WARNING: DiscoPoP configuration: DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY set to default value: 5.") + target_compile_definitions(DiscoPoP_RT PUBLIC DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY=1) + message(STATUS "WARNING: DiscoPoP configuration: DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY set to default value: 0.1%") endif() From 10d87b90764b88e0033be94c8774856024e93f5f Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 10 Jul 2024 12:07:51 +0200 Subject: [PATCH 015/105] Add ci test for false positive reduction --- .../reduction_pattern/negative/__init__.py | 0 .../negative/case_1/__init__.py | 0 .../negative/case_1/src/Makefile | 17 ++++ .../negative/case_1/src/code.cpp | 29 +++++++ .../reduction_pattern/negative/case_1/test.py | 85 +++++++++++++++++++ 5 files changed, 131 insertions(+) create mode 100644 test/end_to_end/reduction_pattern/negative/__init__.py create mode 100644 test/end_to_end/reduction_pattern/negative/case_1/__init__.py create mode 100644 test/end_to_end/reduction_pattern/negative/case_1/src/Makefile create mode 100644 test/end_to_end/reduction_pattern/negative/case_1/src/code.cpp create mode 100644 test/end_to_end/reduction_pattern/negative/case_1/test.py diff --git a/test/end_to_end/reduction_pattern/negative/__init__.py b/test/end_to_end/reduction_pattern/negative/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/end_to_end/reduction_pattern/negative/case_1/__init__.py b/test/end_to_end/reduction_pattern/negative/case_1/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/end_to_end/reduction_pattern/negative/case_1/src/Makefile b/test/end_to_end/reduction_pattern/negative/case_1/src/Makefile new file mode 100644 index 000000000..a64882be3 --- /dev/null +++ b/test/end_to_end/reduction_pattern/negative/case_1/src/Makefile @@ -0,0 +1,17 @@ +all: clean prog + +prog: code.o + $(CXX) -o prog code.o $(CXXFLAGS) + +code.o: + $(CXX) -c -S -emit-llvm -o code.ll code.cpp $(CXXFLAGS) + rm -rf .discopop + $(CXX) -c -o code.o code.cpp $(CXXFLAGS) + +clean: + rm -rf .discopop + rm -rf src/.discopop + find . -not -name code.cpp -not -name Makefile -not -path **/FileMapping.txt -delete + +veryclean: clean + rm -f FileMapping.txt diff --git a/test/end_to_end/reduction_pattern/negative/case_1/src/code.cpp b/test/end_to_end/reduction_pattern/negative/case_1/src/code.cpp new file mode 100644 index 000000000..35859565c --- /dev/null +++ b/test/end_to_end/reduction_pattern/negative/case_1/src/code.cpp @@ -0,0 +1,29 @@ +#include + +int f(int i) { + if (i < 100000 / 2) { + return i + 100000 / 2; + } else { + return i; + } +} + +int g(int i) { return i; } + +int main() { + int N = 100000; + int Arr[N]; + + // DOALL + for (int i = 0; i < N; i++) { + Arr[i] = 0; + } + + long w = 0; + + // NO REDUCTION, NO DOALL + for (int i = 0; i < N; i++) { + w += Arr[g(i)]; + Arr[f(i)] = 1; + } +} \ No newline at end of file diff --git a/test/end_to_end/reduction_pattern/negative/case_1/test.py b/test/end_to_end/reduction_pattern/negative/case_1/test.py new file mode 100644 index 000000000..102624dc2 --- /dev/null +++ b/test/end_to_end/reduction_pattern/negative/case_1/test.py @@ -0,0 +1,85 @@ +import copy +import os +import pathlib +import unittest + +import jsonpickle + +from discopop_library.result_classes.DetectionResult import DetectionResult +from test.utils.existence.existence_utils import check_patterns_for_FN, check_patterns_for_FP +from test.utils.subprocess_wrapper.command_execution_wrapper import run_cmd +from test.utils.validator_classes.DoAllInfoForValidation import DoAllInfoForValidation +from discopop_library.ConfigProvider.config_provider import run as run_config_provider +from discopop_library.ConfigProvider.ConfigProviderArguments import ConfigProviderArguments + + +class TestMethods(unittest.TestCase): + @classmethod + def setUpClass(self): + current_dir = pathlib.Path(__file__).parent.resolve() + dp_build_dir = run_config_provider( + ConfigProviderArguments( + return_dp_build_dir=True, + return_dp_source_dir=False, + return_llvm_bin_dir=False, + return_full_config=False, + return_version_string=False, + ) + ) + + env_vars = dict(os.environ) + + src_dir = os.path.join(current_dir, "src") + + # create FileMapping + cmd = os.path.join(dp_build_dir, "scripts", "dp-fmap") + run_cmd(cmd, src_dir, env_vars) + + # build + env_vars["CC"] = os.path.join(dp_build_dir, "scripts", "CC_wrapper.sh") + env_vars["CXX"] = os.path.join(dp_build_dir, "scripts", "CXX_wrapper.sh") + env_vars["DP_PROJECT_ROOT_DIR"] = src_dir + cmd = "make" + run_cmd(cmd, src_dir, env_vars) + # execute instrumented program + cmd = "./prog" + run_cmd(cmd, src_dir, env_vars) + # execute DiscoPoP analysis + cwd = os.path.join(src_dir, ".discopop") + cmd = "discopop_explorer --enable-patterns doall,reduction" + run_cmd(cmd, cwd, env_vars) + + self.src_dir = src_dir + self.env_vars = env_vars + + test_output_file = os.path.join(self.src_dir, ".discopop", "explorer", "detection_result_dump.json") + # load detection results + with open(test_output_file, "r") as f: + tmp_str = f.read() + self.test_output: DetectionResult = jsonpickle.decode(tmp_str) + + @classmethod + def tearDownClass(self): + run_cmd("make veryclean", self.src_dir, self.env_vars) + + def test(self): + for pattern_type in self.test_output.patterns.__dict__: + amount_of_identified_patterns = len(self.test_output.patterns.__dict__[pattern_type]) + if pattern_type == "do_all": + expected_lines = ["1:18"] + with self.subTest("check for FP"): + res, msg = check_patterns_for_FP(self, pattern_type, copy.deepcopy(expected_lines), self.test_output.patterns.__dict__[pattern_type]) + self.assertTrue(res, msg) + with self.subTest("check for FN"): + res, msg = check_patterns_for_FN(self, pattern_type, copy.deepcopy(expected_lines), self.test_output.patterns.__dict__[pattern_type]) + self.assertTrue(res, msg) + elif pattern_type == "reduction": + expected_lines = [] + with self.subTest("check for FP"): + res, msg = check_patterns_for_FP(self, pattern_type, copy.deepcopy(expected_lines), self.test_output.patterns.__dict__[pattern_type]) + self.assertTrue(res, msg) + with self.subTest("check for FN"): + res, msg = check_patterns_for_FN(self, pattern_type, copy.deepcopy(expected_lines), self.test_output.patterns.__dict__[pattern_type]) + self.assertTrue(res, msg) + else: + self.assertEqual(amount_of_identified_patterns, 0) From 6eb4ea5632ac7b65d0d26d28bf3e90543c68d454 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 10 Jul 2024 15:15:42 +0200 Subject: [PATCH 016/105] added option to mypy.ini --- mypy.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy.ini b/mypy.ini index 0deb6edb6..8952409a5 100644 --- a/mypy.ini +++ b/mypy.ini @@ -29,12 +29,12 @@ no_implicit_reexport = True no_implicit_optional = True strict_equality = True disallow_any_generics = True +check_untyped_defs = True # the following options should be enabled one by one, then we will switch to `strict` type checking: #disallow_untyped_calls = True #disallow_untyped_defs = True #disallow_incomplete_defs = True -#check_untyped_defs = True #warn_unused_ignores = True #extra-checks (command line flag of mypy... is there a way to set it in the config file?) #strict = True From b959b018b27785d0746b23054bbc8a6883cab90a Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 10 Jul 2024 16:47:00 +0200 Subject: [PATCH 017/105] fix: enable mypy --check-untyped-defs --- DEPRECATED_discopop_wizard/screens/utils.py | 4 +- .../screens/widgets/ScrollableText.py | 2 +- discopop_explorer/PEGraphX.py | 10 ++- discopop_explorer/parallel_utils.py | 7 +- discopop_explorer/parser.py | 2 + discopop_explorer/pattern_detection.py | 5 +- .../combined_gpu_patterns/step_6.py | 5 +- .../pattern_detectors/do_all_detector.py | 2 + .../geometric_decomposition_detector.py | 2 + .../pattern_detectors/pipeline_detector.py | 3 + .../pattern_detectors/reduction_detector.py | 4 +- .../task_parallelism/classes.py | 6 +- discopop_explorer/plugins/pipeline.py | 8 +- .../DataTransfers/NewDataTransfers.py | 2 +- .../discopop_optimizer/PETParser/PETParser.py | 86 +++++++++++++------ .../Variables/Experiment.py | 3 + .../classes/types/DataAccessType.py | 4 +- .../gui/queries/ValueTableQuery.py | 4 +- .../gui/widgets/ScrollableFrame.py | 2 +- .../evaluate_all_decision_combinations.py | 4 + .../optimization/evolutionary_algorithm.py | 19 ++++ .../scheduling/workload_delta.py | 8 +- .../suggestions/optimizers/loop_collapse.py | 23 +++-- .../utilities/MOGUtilities.py | 4 +- .../utilities/visualization/plotting.py | 15 ++-- .../utilities/visualization/update_graph.py | 4 +- 26 files changed, 165 insertions(+), 73 deletions(-) diff --git a/DEPRECATED_discopop_wizard/screens/utils.py b/DEPRECATED_discopop_wizard/screens/utils.py index 821b3984f..55e655535 100644 --- a/DEPRECATED_discopop_wizard/screens/utils.py +++ b/DEPRECATED_discopop_wizard/screens/utils.py @@ -27,7 +27,7 @@ def showtip(self, text): x = x + self.widget.winfo_rootx() + 57 y = y + cy + self.widget.winfo_rooty() + 27 self.tip_window = tw = tk.Toplevel(self.widget) - tw.wm_overrideredirect(1) + tw.wm_overrideredirect(True) tw.wm_geometry("+%d+%d" % (x, y)) label = tk.Label( tw, @@ -36,7 +36,7 @@ def showtip(self, text): background="#ffffe0", relief=tk.SOLID, borderwidth=1, - font=("tahoma", "8", "normal"), + font=("tahoma", 8, "normal"), ) label.pack(ipadx=1) diff --git a/DEPRECATED_discopop_wizard/screens/widgets/ScrollableText.py b/DEPRECATED_discopop_wizard/screens/widgets/ScrollableText.py index 6d0b998b4..7f05132ad 100644 --- a/DEPRECATED_discopop_wizard/screens/widgets/ScrollableText.py +++ b/DEPRECATED_discopop_wizard/screens/widgets/ScrollableText.py @@ -15,7 +15,7 @@ class ScrollableTextWidget(object): text_container: tk.Text def __init__(self, parent_frame): - self.frame = ttk.Frame(parent_frame) + self.frame = ttk.Frame(parent_frame) # type: ignore self.frame.pack(fill=tk.BOTH, expand=True) self.frame.rowconfigure(0, weight=1) self.frame.columnconfigure(0, weight=1) diff --git a/discopop_explorer/PEGraphX.py b/discopop_explorer/PEGraphX.py index 41432f936..c026a7da0 100644 --- a/discopop_explorer/PEGraphX.py +++ b/discopop_explorer/PEGraphX.py @@ -735,6 +735,8 @@ def map_static_and_dynamic_dependencies(self): for _, _, d2 in out_deps: if d1.var_name == d2.var_name: if d1.memory_region != d2.memory_region: + if d1.memory_region is None or d2.memory_region is None: + continue if d1.memory_region not in mem_reg_mappings: mem_reg_mappings[d1.memory_region] = set() if d2.memory_region not in mem_reg_mappings: @@ -748,6 +750,8 @@ def map_static_and_dynamic_dependencies(self): for node_id in [n.id for n in self.all_nodes(CUNode)]: out_deps = [(s, t, d) for s, t, d in self.out_edges(node_id) if d.etype == EdgeType.DATA] for s, t, d in out_deps: + if d.memory_region is None: + continue if d.memory_region.startswith("S"): # Static dependency found # check if mappings exist @@ -889,7 +893,7 @@ def calculateLoopMetadata(self): # identify loop indices loop_indices: Set[Variable] = set() for v in candidates: - if self.is_loop_index(v.name, loop.start_position(), subtree): + if self.is_loop_index(v.name, [loop.start_position()], subtree): loop_indices.add(v) loop.loop_indices = [v.name for v in loop_indices] print("\tDone.") @@ -902,7 +906,7 @@ def show(self): :return: """ # print("showing") - plt.plot() + plt.plot() # type: ignore pos = self.pos # draw nodes @@ -1672,6 +1676,8 @@ def dump_to_gephi_file(self, name="pet.gexf"): self.g.edges[edge]["edge_type"] = str(dep.etype.name) if dep.etype == EdgeType.DATA: self.g.edges[edge]["var"] = dep.var_name + if dep.dtype is None: + raise ValueError("dep.dtype has no type name!") self.g.edges[edge]["dep_type"] = str(dep.dtype.name) nx.write_gexf(self.g, name) diff --git a/discopop_explorer/parallel_utils.py b/discopop_explorer/parallel_utils.py index 99d0dea39..88ceddc9d 100644 --- a/discopop_explorer/parallel_utils.py +++ b/discopop_explorer/parallel_utils.py @@ -6,10 +6,10 @@ # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. -from .PEGraphX import Node, NodeID +from .PEGraphX import Node, NodeID, PEGraphX from typing import List, Set -global_pet = None +global_pet: None | PEGraphX = None def pet_function_metadata_initialize_worker(pet): @@ -18,6 +18,9 @@ def pet_function_metadata_initialize_worker(pet): def pet_function_metadata_parse_func(func_node): + if global_pet is None: + raise ValueError("global_pet is None!") + stack: List[Node] = global_pet.direct_children(func_node) func_node.children_cu_ids = [node.id for node in stack] local_children: Set[NodeID] = set() diff --git a/discopop_explorer/parser.py b/discopop_explorer/parser.py index c950ec9c0..9bbcd9984 100644 --- a/discopop_explorer/parser.py +++ b/discopop_explorer/parser.py @@ -249,6 +249,8 @@ def is_reduction(reduction_line, fmap_lines, file_mapping): if not rex: return False res = rex.search(reduction_line) + if res is None: + return False file_id = int(res.group(1)) file_line = int(res.group(2)) diff --git a/discopop_explorer/pattern_detection.py b/discopop_explorer/pattern_detection.py index 3ee7285a8..a4a78e741 100644 --- a/discopop_explorer/pattern_detection.py +++ b/discopop_explorer/pattern_detection.py @@ -8,6 +8,7 @@ import json import os import sys +from typing import cast from alive_progress import alive_bar # type: ignore @@ -28,7 +29,7 @@ from .pattern_detectors.do_all_detector import DoAllInfo, run_detection as detect_do_all from .pattern_detectors.geometric_decomposition_detector import run_detection as detect_gd from .pattern_detectors.pipeline_detector import run_detection as detect_pipeline -from .pattern_detectors.reduction_detector import run_detection as detect_reduction +from .pattern_detectors.reduction_detector import ReductionInfo, run_detection as detect_reduction from .pattern_detectors.simple_gpu_patterns.gpu_pattern_detector import run_detection as detect_gpu @@ -289,6 +290,6 @@ def __get_red_var_obj_from_name(name): pt.last_private = [__get_var_obj_from_name(v) for v in pattern_dict["last_private"]] pt.shared = [__get_var_obj_from_name(v) for v in pattern_dict["shared"]] pt.reduction = [__get_red_var_obj_from_name(v) for v in pattern_dict["reduction"]] - res.patterns.reduction.append(pt) + res.patterns.reduction.append(cast(ReductionInfo, pt)) return res diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py index 3c59a4edf..35d4b19b7 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py @@ -7,7 +7,7 @@ # directory for details. import copy import sys -from typing import Set, Tuple, Dict, List, cast, Optional, Union +from typing import Any, Set, Tuple, Dict, List, cast, Optional, Union from networkx import MultiDiGraph # type: ignore @@ -354,7 +354,7 @@ def remove_duplicates(target_set: Union[Set[Update], Set[EntryPoint], Set[ExitPo def join_elements(target_set): - grouping_dict = dict() + grouping_dict: Dict[Any, List[Any]] = dict() for elem in target_set: if elem.get_position_identifier() not in grouping_dict: @@ -372,4 +372,5 @@ def join_elements(target_set): else: joined_entry_point.join(elem) result_set.add(cast(EntryPoint, joined_entry_point)) + return result_set diff --git a/discopop_explorer/pattern_detectors/do_all_detector.py b/discopop_explorer/pattern_detectors/do_all_detector.py index 0b9ea1727..3e38fa573 100644 --- a/discopop_explorer/pattern_detectors/do_all_detector.py +++ b/discopop_explorer/pattern_detectors/do_all_detector.py @@ -123,6 +123,8 @@ def __check_node(param_tuple): global global_pet local_result = [] node = param_tuple + if global_pet is None: + raise ValueError("global_pet is None!") if __detect_do_all(global_pet, node): node.do_all = True diff --git a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py index f62b5352d..d02ab86f6 100644 --- a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py +++ b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py @@ -119,6 +119,8 @@ def __check_node(param_tuple): global global_pet local_result = [] node = param_tuple + if global_pet is None: + raise ValueError("global_pet is None!") if __detect_geometric_decomposition(global_pet, node): node.geometric_decomposition = True diff --git a/discopop_explorer/pattern_detectors/pipeline_detector.py b/discopop_explorer/pattern_detectors/pipeline_detector.py index 4cc983d49..de70de80f 100644 --- a/discopop_explorer/pattern_detectors/pipeline_detector.py +++ b/discopop_explorer/pattern_detectors/pipeline_detector.py @@ -192,6 +192,9 @@ def __check_node(param_tuple): node = param_tuple + if global_pet is None: + raise ValueError("global_pet is None!") + node.pipeline = __detect_pipeline(global_pet, node) if node.pipeline > __pipeline_threshold: local_result.append(PipelineInfo(global_pet, node)) diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index d51f27a31..3afc2494d 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -58,7 +58,7 @@ def __str__(self): f"private: {[v.name for v in self.private]}\n" f"shared: {[v.name for v in self.shared]}\n" f"first private: {[v.name for v in self.first_private]}\n" - f'reduction: {[v.operation + ":" + v.name for v in self.reduction]}\n' + f'reduction: {[str(v.operation) + ":" + v.name for v in self.reduction]}\n' f"last private: {[v.name for v in self.last_private]}" ) @@ -106,6 +106,8 @@ def __check_node(param_tuple): global global_pet local_result = [] node = param_tuple + if global_pet is None: + raise ValueError("global_pet is None!") if __detect_reduction(global_pet, node): node.reduction = True if node.loop_iterations >= 0 and not node.contains_array_reduction: diff --git a/discopop_explorer/pattern_detectors/task_parallelism/classes.py b/discopop_explorer/pattern_detectors/task_parallelism/classes.py index 28cf7ee3a..b2ad620a9 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/classes.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/classes.py @@ -163,7 +163,7 @@ def __str__(self): f"CU Start line: {self.start_line}\n" f"CU End line: {self.end_line}\n" f"Combinable with: {self.cwn_id}\n" - f'in_dep: {" ".join(self.in_dep)}\n' - f'out_dep: {" ".join(self.out_dep)}\n' - f'in_out_dep: {" ".join(self.in_out_dep)}\n' + f'in_dep: {" ".join([str(s) for s in self.in_dep])}\n' + f'out_dep: {" ".join([str(s) for s in self.out_dep])}\n' + f'in_out_dep: {" ".join([str(s) for s in self.in_out_dep])}\n' ) diff --git a/discopop_explorer/plugins/pipeline.py b/discopop_explorer/plugins/pipeline.py index df49fc611..2a1a07a18 100644 --- a/discopop_explorer/plugins/pipeline.py +++ b/discopop_explorer/plugins/pipeline.py @@ -142,11 +142,11 @@ def get_correlation_coefficient(matrix): for i in range(0, len(matrix) - 1): graph_vector.append(matrix[i + 1][i]) - pipeline_vector = [] + pipeline_vector: List[float] = [] for i in range(0, len(matrix) - 1): - pipeline_vector.append(1) + pipeline_vector.append(1.0) - min_weight = 1 + min_weight = 1.0 for i in range(0, len(matrix) - 1): for j in range(i + 1, len(matrix)): if matrix[i][j] == 1: @@ -156,7 +156,7 @@ def get_correlation_coefficient(matrix): if min_weight == 1: graph_vector.append(0) - pipeline_vector.append(0) + pipeline_vector.append(0.0) else: graph_vector.append(1) pipeline_vector.append(min_weight) diff --git a/discopop_library/discopop_optimizer/DataTransfers/NewDataTransfers.py b/discopop_library/discopop_optimizer/DataTransfers/NewDataTransfers.py index b5bccbc7b..de1366327 100644 --- a/discopop_library/discopop_optimizer/DataTransfers/NewDataTransfers.py +++ b/discopop_library/discopop_optimizer/DataTransfers/NewDataTransfers.py @@ -310,7 +310,7 @@ def log_state(self): for device_id in self.entered_data_regions_by_device: logger.debug("-> Device: " + str(device_id)) for wda in self.entered_data_regions_by_device[device_id]: - logger.debug("\t-> " + str(wda.memory_region) + " : " + wda.var_name) + logger.debug("\t-> " + str(wda.memory_region) + " : " + str(wda.var_name)) logger.debug("") diff --git a/discopop_library/discopop_optimizer/PETParser/PETParser.py b/discopop_library/discopop_optimizer/PETParser/PETParser.py index bb7a31412..d88abbfd2 100644 --- a/discopop_library/discopop_optimizer/PETParser/PETParser.py +++ b/discopop_library/discopop_optimizer/PETParser/PETParser.py @@ -14,6 +14,8 @@ import networkx as nx # type: ignore import warnings +from sympy import Integer + from discopop_explorer.PEGraphX import ( PEGraphX, FunctionNode, @@ -194,6 +196,8 @@ def __add_calling_edges(self): if type(node_data) != Workload: continue # get functions called by the node + if node_data.original_cu_id is None: + raise ValueError("Node: " + str(node) + " has no original_cu_id") for out_call_edge in self.experiment.detection_result.pet.out_edges( node_data.original_cu_id, etype=EdgeType.CALLSNODE ): @@ -282,10 +286,10 @@ def __prune_branches(self): if valid_target: current_node_cu_id = data_at(self.graph, current_node).original_cu_id # calculate likelihood for current_node - likelihood = 0 + likelihood = 0.0 for pred in predecessors: pred_cu_id = data_at(self.graph, pred).original_cu_id - edge_likelihood = 1 # fallback if no data exists or not a branching point + edge_likelihood = 1.0 # fallback if no data exists or not a branching point if len(get_successors(self.graph, pred)) > 1: if pred_cu_id in branch_likelihood_dict: if current_node_cu_id in branch_likelihood_dict[pred_cu_id]: @@ -430,7 +434,7 @@ def __flatten_function_graphs(self): # show_function(self.graph, function_node, show_dataflow=False, show_mutex_edges=False) ## dbg show profiling data - if self.experiment.arguments.profiling: + if self.experiment.arguments.profiling and self.experiment.profile is not None: self.experiment.profile.disable() if os.path.exists("optimizer_profile.txt"): os.remove("optimizer_profile.txt") @@ -467,7 +471,7 @@ def __flatten_function_graphs(self): iteration_time = int(time()) if iteration_time - start_time > timeout: ## dbg show profiling data - if self.experiment.arguments.profiling: + if self.experiment.arguments.profiling and self.experiment.profile is not None: self.experiment.profile.disable() if os.path.exists("optimizer_profile.txt"): os.remove("optimizer_profile.txt") @@ -633,7 +637,11 @@ def __remove_non_hotspot_function_bodys(self): # convert raw information to node ids for file_id, name in all_hotspot_functions_raw: for function in get_all_function_nodes(self.graph): - function_node = data_at(self.graph, function) + function_node = cast(FunctionRoot, data_at(self.graph, function)) + if function_node is None: + continue + if function_node.original_cu_id is None: + continue if int(function_node.original_cu_id.split(":")[0]) == file_id: print("FID EQUAL") print("CHECK NAME: ", function_node.name, name) @@ -649,7 +657,7 @@ def __remove_non_hotspot_function_bodys(self): function not in self.experiment.hotspot_function_node_ids and len(self.experiment.hotspot_function_node_ids) > 0 ): - print("DELETING FUNCTION BODY: ", data_at(self.graph, function).name) + print("DELETING FUNCTION BODY: ", cast(FunctionRoot, data_at(self.graph, function)).name) # remove function body for node in get_all_nodes_in_function(self.graph, function): self.graph.remove_node(node) @@ -658,7 +666,7 @@ def __remove_non_hotspot_function_bodys(self): def __remove_invalid_functions(self): for function in self.invalid_functions: if self.experiment.arguments.verbose: - print("Removing body of invalid function: ", data_at(self.graph, function).name) + print("Removing body of invalid function: ", cast(FunctionRoot, data_at(self.graph, function)).name) # delete all nodes in function body for node in get_all_nodes_in_function(self.graph, function): self.graph.remove_node(node) @@ -726,7 +734,7 @@ def __add_function_return_node(self): def __add_branch_return_node(self): """makes sure every branching section has a merge node""" - path_return_nodes: Dict[int, int] = dict() + path_return_nodes: Dict[List[int], int] = dict() for node in copy.deepcopy(self.graph.nodes()): if len(get_successors(self.graph, node)) == 0: @@ -754,13 +762,19 @@ def __new_parse_branched_sections(self): function not in self.experiment.hotspot_function_node_ids and len(self.experiment.hotspot_function_node_ids) > 0 ): - if data_at(self.graph, function).name == "main": - print("SKIPPING NON HOTSPOT FUNCTION: ", data_at(self.graph, function).name) + if cast(FunctionRoot, data_at(self.graph, function)).name == "main": + print("SKIPPING NON HOTSPOT FUNCTION: ", cast(FunctionRoot, data_at(self.graph, function)).name) continue # try: if self.experiment.arguments.verbose: - if data_at(self.graph, function).name == "main": - print("FUNCTION: ", data_at(self.graph, function).name, idx, "/", len(all_functions)) + if cast(FunctionRoot, data_at(self.graph, function)).name == "main": + print( + "FUNCTION: ", + cast(FunctionRoot, data_at(self.graph, function)).name, + idx, + "/", + len(all_functions), + ) nodes_in_function = nodes_by_functions[function] post_dominators = self.__get_post_dominators(nodes_in_function) @@ -768,15 +782,25 @@ def __new_parse_branched_sections(self): path_splits = self.__get_path_splits(nodes_in_function) merge_nodes = self.__get_merge_nodes(path_splits, post_dominators) - if data_at(self.graph, function).name == "main": + if cast(FunctionRoot, data_at(self.graph, function)).name == "main": print("showing..") - show_function(self.graph, data_at(self.graph, function), show_dataflow=False, show_mutex_edges=False) + show_function( + self.graph, + cast(FunctionRoot, data_at(self.graph, function)), + show_dataflow=False, + show_mutex_edges=False, + ) added_node_ids = self.__fix_empty_branches(merge_nodes, post_dominators) - if data_at(self.graph, function).name == "main": + if cast(FunctionRoot, data_at(self.graph, function)).name == "main": print("showing..") - show_function(self.graph, data_at(self.graph, function), show_dataflow=False, show_mutex_edges=False) + show_function( + self.graph, + cast(FunctionRoot, data_at(self.graph, function)), + show_dataflow=False, + show_mutex_edges=False, + ) nodes_in_function = list(set(nodes_in_function).union(set(added_node_ids))) # re-calculate post_dominators and merge nodes @@ -785,9 +809,14 @@ def __new_parse_branched_sections(self): # merge_nodes = self.__get_merge_nodes(path_splits, post_dominators) self.__insert_context_nodes(nodes_in_function) - if data_at(self.graph, function).name == "main": + if cast(FunctionRoot, data_at(self.graph, function)).name == "main": print("showing..") - show_function(self.graph, data_at(self.graph, function), show_dataflow=False, show_mutex_edges=False) + show_function( + self.graph, + cast(FunctionRoot, data_at(self.graph, function)), + show_dataflow=False, + show_mutex_edges=False, + ) # sanity check # fix_applied = True @@ -1175,8 +1204,8 @@ def __add_cu_nodes(self): node_id=new_node_id, experiment=self.experiment, cu_id=cu_node.id, - sequential_workload=0, - parallelizable_workload=parallelizable_workload, + sequential_workload=Integer(0), + parallelizable_workload=Integer(parallelizable_workload), written_memory_regions=written_memory_regions, read_memory_regions=read_memory_regions, ), @@ -1219,7 +1248,10 @@ def __add_loop_nodes(self): ), ) # connect loop node and entry node via a child edge - entry_node_cu_id = loop_node.get_entry_node(self.pet).id + tmp_entry_node = loop_node.get_entry_node(self.pet) + if tmp_entry_node is None: + raise ValueError("Loop: " + str(loop_node) + " has no entry node!") + entry_node_cu_id = tmp_entry_node.id add_child_edge(self.graph, new_node_id, self.cu_id_to_graph_node_id[entry_node_cu_id]) # redirect edges from outside the loop to the entry node to the Loop node @@ -1390,7 +1422,7 @@ def inlined_data_flow_calculation(current_node, current_last_writes): if self.experiment.arguments.verbose: print( "Calculating dataflow for function: ", - data_at(self.graph, function_node).name, + cast(FunctionRoot, data_at(self.graph, function_node)).name, idx, "/", len(all_function_nodes), @@ -1399,10 +1431,10 @@ def inlined_data_flow_calculation(current_node, current_last_writes): function_node not in self.experiment.hotspot_function_node_ids and len(self.experiment.hotspot_function_node_ids) > 0 ): - print("SKIPPING NON-HOTSPOT FUNCTION: ", data_at(self.graph, function_node).name) + print("SKIPPING NON-HOTSPOT FUNCTION: ", cast(FunctionRoot, data_at(self.graph, function_node)).name) continue if function_node in self.invalid_functions: - print("SKIPPING INVALID FUNCTION: ", data_at(self.graph, function_node).name) + print("SKIPPING INVALID FUNCTION: ", cast(FunctionRoot, data_at(self.graph, function_node)).name) continue try: @@ -1412,7 +1444,7 @@ def inlined_data_flow_calculation(current_node, current_last_writes): if self.experiment.arguments.verbose: print( "CDF: Function:", - data_at(self.graph, function_node).name, + cast(FunctionRoot, data_at(self.graph, function_node)).name, "invalid due to graph construction errors. Skipping.", ) # show_function(self.graph, data_at(self.graph, function_node), show_dataflow=False, show_mutex_edges=False) @@ -1420,7 +1452,9 @@ def inlined_data_flow_calculation(current_node, current_last_writes): except IndexError: # function has no child. ignore, but issue a warning warnings.warn( - "Skipping function: " + data_at(self.graph, function_node).name + " as it has no children nodes!" + "Skipping function: " + + cast(FunctionRoot, data_at(self.graph, function_node)).name + + " as it has no children nodes!" ) pass diff --git a/discopop_library/discopop_optimizer/Variables/Experiment.py b/discopop_library/discopop_optimizer/Variables/Experiment.py index 47db2fda7..56db58eea 100644 --- a/discopop_library/discopop_optimizer/Variables/Experiment.py +++ b/discopop_library/discopop_optimizer/Variables/Experiment.py @@ -5,6 +5,7 @@ # This software may be modified and distributed under the terms of # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. +from cProfile import Profile import os from pathlib import Path from typing import Dict, Tuple, Set, Optional, List, Any @@ -79,6 +80,8 @@ class Experiment(object): hotspot_functions: Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]] hotspot_function_node_ids: List[int] + profile: Optional[Profile] + def __init__( self, file_mapping: Dict[int, Path], diff --git a/discopop_library/discopop_optimizer/classes/types/DataAccessType.py b/discopop_library/discopop_optimizer/classes/types/DataAccessType.py index 4b1a03dab..5f3b2ff83 100644 --- a/discopop_library/discopop_optimizer/classes/types/DataAccessType.py +++ b/discopop_library/discopop_optimizer/classes/types/DataAccessType.py @@ -42,14 +42,14 @@ def __init__(self, memory_region: MemoryRegion, unique_id: int, var_name: Option def __str__(self): return_str = "" return_str += "C" if self.from_call else "" - return_str += "W(" + self.memory_region + "-" + str(self.unique_id) + ", --> " + self.var_name + ")" + return_str += "W(" + self.memory_region + "-" + str(self.unique_id) + ", --> " + str(self.var_name) + ")" return return_str def __hash__(self): return self.unique_id def toDict(self): - result_dict = {} + result_dict: Dict[str, Any] = {} result_dict["memory_region"] = self.memory_region result_dict["unique_id"] = self.unique_id result_dict["var_name"] = self.var_name diff --git a/discopop_library/discopop_optimizer/gui/queries/ValueTableQuery.py b/discopop_library/discopop_optimizer/gui/queries/ValueTableQuery.py index 003acd081..2ca1f1393 100644 --- a/discopop_library/discopop_optimizer/gui/queries/ValueTableQuery.py +++ b/discopop_library/discopop_optimizer/gui/queries/ValueTableQuery.py @@ -7,7 +7,7 @@ # directory for details. import tkinter as tk from tkinter import * -from typing import List, Tuple, Optional, Dict, cast, Union +from typing import Any, List, Tuple, Optional, Dict, cast, Union from sympy import Symbol, Expr @@ -120,7 +120,7 @@ def onPress(): for row_idx, row in enumerate(rows): if row_idx == 0: continue - row_element = [] + row_element: List[Any] = [] for col_idx, col in enumerate(row): if col_idx == 0: # append symbol to row_element diff --git a/discopop_library/discopop_optimizer/gui/widgets/ScrollableFrame.py b/discopop_library/discopop_optimizer/gui/widgets/ScrollableFrame.py index 56cbec48b..b68fe4626 100644 --- a/discopop_library/discopop_optimizer/gui/widgets/ScrollableFrame.py +++ b/discopop_library/discopop_optimizer/gui/widgets/ScrollableFrame.py @@ -19,7 +19,7 @@ def __init__(self, parent_frame): self.container = ttk.Frame(parent_frame) self.canvas = tk.Canvas(self.container) self.scrollbar = ttk.Scrollbar(self.container, orient="vertical", command=self.canvas.yview) - self.scrollable_frame = ttk.Frame(self.canvas) + self.scrollable_frame = ttk.Frame(self.canvas) # type: ignore # configure weights self.container.rowconfigure(0, weight=1) diff --git a/discopop_library/discopop_optimizer/optimization/evaluate_all_decision_combinations.py b/discopop_library/discopop_optimizer/optimization/evaluate_all_decision_combinations.py index 73957df89..345e4cdf9 100644 --- a/discopop_library/discopop_optimizer/optimization/evaluate_all_decision_combinations.py +++ b/discopop_library/discopop_optimizer/optimization/evaluate_all_decision_combinations.py @@ -139,6 +139,10 @@ def __initialize_worker( def __evaluate_configuration(param_tuple): global global_experiment global global_arguments + if global_experiment is None: + raise ValueError("global_experiment is None!") + if global_arguments is None: + raise ValueError("global_arguments is None!") decisions = param_tuple return evaluate_configuration(global_experiment, decisions, global_arguments) diff --git a/discopop_library/discopop_optimizer/optimization/evolutionary_algorithm.py b/discopop_library/discopop_optimizer/optimization/evolutionary_algorithm.py index 242c5a3c6..e96edfb92 100644 --- a/discopop_library/discopop_optimizer/optimization/evolutionary_algorithm.py +++ b/discopop_library/discopop_optimizer/optimization/evolutionary_algorithm.py @@ -194,6 +194,12 @@ def __parallel_get_random_configuration(param_tuple): global global_experiment global global_arguments global global_available_decisions + if global_experiment is None: + raise ValueError("global_experiment is None!") + if global_arguments is None: + raise ValueError("global_arguments is None!") + if global_population is None: + raise ValueError("global_population is None!") return __get_random_configuration(global_experiment, global_available_decisions, global_arguments) @@ -313,6 +319,13 @@ def __parallel_crossover(param_tuple): global global_arguments global global_population + if global_experiment is None: + raise ValueError("global_experiment is None!") + if global_arguments is None: + raise ValueError("global_arguments is None!") + if global_population is None: + raise ValueError("global_population is None!") + for i in range(0, 1000): # select two random elements element_1 = random.choice(global_population) @@ -378,6 +391,12 @@ def __parallel_mutate(param_tuple): global global_experiment global global_arguments global global_population + if global_experiment is None: + raise ValueError("global_experiment is None!") + if global_arguments is None: + raise ValueError("global_arguments is None!") + if global_population is None: + raise ValueError("global_population is None!") for i in range(0, 1000): # select random mutation target from population diff --git a/discopop_library/discopop_optimizer/scheduling/workload_delta.py b/discopop_library/discopop_optimizer/scheduling/workload_delta.py index 86d368a19..dbc22f776 100644 --- a/discopop_library/discopop_optimizer/scheduling/workload_delta.py +++ b/discopop_library/discopop_optimizer/scheduling/workload_delta.py @@ -34,7 +34,9 @@ class BranchCosts(RegularCosts): class WorkloadStack(object): - stack: List[Union[List[Any], RegularCosts]] # List of WorkloadStacks or integer tuples (min_wl, max_wl) + stack: List[ + Any + ] # List[Union[List[Any], RegularCosts]] # List of WorkloadStacks or integer tuples (min_wl, max_wl) def __init__(self): self.stack = [] @@ -104,8 +106,8 @@ def aggregate(self): max_branch_wl = max_costs # accumulate total costs for branched section - min_wl += 0 if min_branch_wl is None else cast(int, min_branch_wl) - max_wl += 0 if max_branch_wl is None else cast(int, max_branch_wl) + min_wl += 0 if min_branch_wl is None else min_branch_wl + max_wl += 0 if max_branch_wl is None else max_branch_wl # replace innermost stack with accumulated costs cur_elem = self.stack diff --git a/discopop_library/discopop_optimizer/suggestions/optimizers/loop_collapse.py b/discopop_library/discopop_optimizer/suggestions/optimizers/loop_collapse.py index 0fd76d53f..dd7fcef96 100644 --- a/discopop_library/discopop_optimizer/suggestions/optimizers/loop_collapse.py +++ b/discopop_library/discopop_optimizer/suggestions/optimizers/loop_collapse.py @@ -81,6 +81,11 @@ def __collapse_loops_in_function(function_node_id): global global_graph global global_experiment + if global_experiment is None: + raise ValueError("global_experiment is None!") + if global_graph is None: + raise ValueError("global_graph is None!") + modifiation_found = True return_value = False visited_inner_loop: Set[int] = set() @@ -97,7 +102,7 @@ def __collapse_loops_in_function(function_node_id): # loops = get_all_loop_nodes(global_graph) for loop in copy.deepcopy(relevant_loops): logging.info("Checking loop collapse for @ " + str(loop)) - loop_data = data_at(global_graph, loop) + loop_data = cast(Loop, data_at(global_graph, loop)) # if function_node_id not in get_all_parents(global_graph, loop): # continue # loop contained in function @@ -148,7 +153,7 @@ def __collapse_loops_in_function(function_node_id): # parent is empty node -> skip if isinstance(current_data, Workload): - if cast(Workload, current_data).sequential_workload == Integer(0): + if current_data.sequential_workload == Integer(0): queue += get_parents(global_graph, current) continue # parent is regular node -> end search on this path (no perfect nesting) @@ -159,7 +164,7 @@ def __collapse_loops_in_function(function_node_id): invalid: Set[int] = set() for csrc in collapse_sources: # check that only a single loop exists as a direct child - queue: List[int] = get_children(global_graph, csrc) + queue = get_children(global_graph, csrc) ignore_list: List[int] = [] found_loop: bool = False while queue: @@ -184,12 +189,14 @@ def __collapse_loops_in_function(function_node_id): # create new collapse node new_node_id = global_experiment.get_next_free_node_id() relevant_loops.add(new_node_id) - node_data_copy = copy.deepcopy(data_at(global_graph, csrc)) + node_data_copy = cast(Loop, copy.deepcopy(data_at(global_graph, csrc))) node_data_copy.node_id = new_node_id # increase and set collapse level - cast(Loop, node_data_copy).collapse_level = loop_data.collapse_level + 1 + node_data_copy.collapse_level = loop_data.collapse_level + 1 # register a new pattern + if node_data_copy.original_cu_id is None: + raise ValueError("Node is not assigned to an original cu id!") pattern_info = DoAllInfo( global_experiment.detection_result.pet, global_experiment.detection_result.pet.node_at(node_data_copy.original_cu_id), @@ -260,11 +267,11 @@ def __collapse_loops_in_function(function_node_id): Loop, data_at(global_graph, seq_loop_option) ).iterations cast(Loop, data_at(global_graph, new_node_id)).iterations_symbol = Symbol( - "loop_" + str(new_node_id) + "_pos_" + str(cast(Loop, node_data_copy).position) + "_iterations" + "loop_" + str(new_node_id) + "_pos_" + str(node_data_copy.position) + "_iterations" ) global_experiment.register_free_symbol( - cast(Loop, node_data_copy).iterations_symbol, - value_suggestion=Integer(cast(Loop, node_data_copy).iterations), + node_data_copy.iterations_symbol, + value_suggestion=Integer(node_data_copy.iterations), ) # create a new requirements edge to the single-iteration sequential version of the inner loop diff --git a/discopop_library/discopop_optimizer/utilities/MOGUtilities.py b/discopop_library/discopop_optimizer/utilities/MOGUtilities.py index 802315464..2d1bba9f5 100644 --- a/discopop_library/discopop_optimizer/utilities/MOGUtilities.py +++ b/discopop_library/discopop_optimizer/utilities/MOGUtilities.py @@ -363,11 +363,11 @@ def hover(event): if cont: update_annot(ind, node_ids[node_type]) annot.set_visible(True) - fig.canvas.draw_idle() + fig.canvas.draw_idle() # type: ignore else: if vis: annot.set_visible(False) - fig.canvas.draw_idle() + fig.canvas.draw_idle() # type: ignore except TypeError: pass diff --git a/discopop_library/discopop_optimizer/utilities/visualization/plotting.py b/discopop_library/discopop_optimizer/utilities/visualization/plotting.py index b31a91452..ddbaf0ec3 100644 --- a/discopop_library/discopop_optimizer/utilities/visualization/plotting.py +++ b/discopop_library/discopop_optimizer/utilities/visualization/plotting.py @@ -5,6 +5,7 @@ # This software may be modified and distributed under the terms of # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. +from typing import Any, Dict, List import matplotlib.pyplot as plt # type: ignore import networkx as nx # type: ignore @@ -39,9 +40,9 @@ def show(graph): pos = nx.random_layout(graph) drawn_nodes = set() - nodes_lists = dict() - node_ids = dict() - node_insertion_sequence = [] + nodes_lists: Dict[Any, Any] = dict() + node_ids: Dict[Any, Any] = dict() + node_insertion_sequence: List[Any] = [] # draw nodes node_insertion_sequence.append(FunctionRoot) nodes_lists[FunctionRoot] = nx.draw_networkx_nodes( @@ -143,7 +144,7 @@ def show(graph): # define tool tip style when hovering # based on https://stackoverflow.com/questions/61604636/adding-tooltip-for-nodes-in-python-networkx-graph - annot = ax.annotate( + annot = ax.annotate( # type: ignore "", xy=(0, 0), xytext=(20, 20), @@ -177,13 +178,13 @@ def hover(event): if cont: update_annot(ind, node_ids[node_type]) annot.set_visible(True) - fig.canvas.draw_idle() + fig.canvas.draw_idle() # type: ignore else: if vis: annot.set_visible(False) - fig.canvas.draw_idle() + fig.canvas.draw_idle() # type: ignore except TypeError: pass - fig.canvas.mpl_connect("motion_notify_event", hover) + fig.canvas.mpl_connect("motion_notify_event", hover) # type: ignore plt.show() diff --git a/discopop_library/discopop_optimizer/utilities/visualization/update_graph.py b/discopop_library/discopop_optimizer/utilities/visualization/update_graph.py index 17fa9ea8f..2017eed2f 100644 --- a/discopop_library/discopop_optimizer/utilities/visualization/update_graph.py +++ b/discopop_library/discopop_optimizer/utilities/visualization/update_graph.py @@ -195,11 +195,11 @@ def hover(event): if cont: update_annot(ind, node_ids[node_type]) annot.set_visible(True) - fig.canvas.draw_idle() + fig.canvas.draw_idle() # type: ignore else: if vis: annot.set_visible(False) - fig.canvas.draw_idle() + fig.canvas.draw_idle() # type: ignore except TypeError: pass From 1e6205cd568c8f1552a1a4073e1126dbf4f233de Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 10 Jul 2024 16:50:09 +0200 Subject: [PATCH 018/105] fix: python 3.8 compatibility --- discopop_explorer/parallel_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/discopop_explorer/parallel_utils.py b/discopop_explorer/parallel_utils.py index 88ceddc9d..79ae448e0 100644 --- a/discopop_explorer/parallel_utils.py +++ b/discopop_explorer/parallel_utils.py @@ -7,9 +7,9 @@ # directory for details. from .PEGraphX import Node, NodeID, PEGraphX -from typing import List, Set +from typing import List, Optional, Set -global_pet: None | PEGraphX = None +global_pet: Optional[PEGraphX] = None def pet_function_metadata_initialize_worker(pet): From 6db4051a304657ff952629fc1a6896e5373e7510 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 10 Jul 2024 17:02:51 +0200 Subject: [PATCH 019/105] mypy: add --disallow-incomplete-defs --- mypy.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy.ini b/mypy.ini index 8952409a5..728aa51a1 100644 --- a/mypy.ini +++ b/mypy.ini @@ -30,11 +30,11 @@ no_implicit_optional = True strict_equality = True disallow_any_generics = True check_untyped_defs = True +disallow_incomplete_defs = True # the following options should be enabled one by one, then we will switch to `strict` type checking: #disallow_untyped_calls = True #disallow_untyped_defs = True -#disallow_incomplete_defs = True #warn_unused_ignores = True #extra-checks (command line flag of mypy... is there a way to set it in the config file?) #strict = True From bed0b346b620ce6bb15cb30e913e023cf436c4b6 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Thu, 11 Jul 2024 16:42:46 +0200 Subject: [PATCH 020/105] chore(mypy): add type annotations --- .github/workflows/ci.yml | 20 +- .../screens/widgets/ScrollableText.py | 2 +- discopop_explorer/PEGraphX.py | 33 +- discopop_explorer/discopop_explorer.py | 2 +- discopop_explorer/generate_Data_CUInst.py | 11 +- discopop_explorer/parser.py | 3 +- discopop_explorer/pattern_detection.py | 38 +- .../CombinedGPURegions.py | 25 +- .../classes/EntryPoint.py | 8 +- .../classes/ExitPoint.py | 8 +- .../combined_gpu_patterns/classes/Update.py | 32 +- .../combined_gpu_pattern_detector.py | 8 +- .../combined_gpu_patterns/step_1.py | 7 +- .../combined_gpu_patterns/step_2.py | 18 +- .../combined_gpu_patterns/step_3.py | 3 +- .../combined_gpu_patterns/step_4.py | 23 +- .../combined_gpu_patterns/step_6.py | 4 +- .../combined_gpu_patterns/utilities.py | 2 +- .../pattern_detectors/do_all_detector.py | 15 +- .../geometric_decomposition_detector.py | 7 +- .../pattern_detectors/pipeline_detector.py | 27 +- .../pattern_detectors/reduction_detector.py | 13 +- .../simple_gpu_patterns/GPULoop.py | 9 +- .../simple_gpu_patterns/GPURegions.py | 6 +- .../gpu_pattern_detector.py | 9 +- .../simple_gpu_patterns/utils.py | 3 +- .../task_parallelism/alias_detection.py | 2 +- .../task_parallelism/classes.py | 21 +- .../task_parallelism/filter.py | 31 +- .../task_parallelism/preprocessor.py | 6 +- .../task_parallelism/suggesters/barriers.py | 4 +- .../suggesters/dependency_clauses.py | 28 +- .../task_parallelism/suggesters/tasks.py | 19 +- .../task_parallelism_detector.py | 11 +- .../task_parallelism/tp_utils.py | 10 +- discopop_explorer/plugins/pipeline.py | 6 +- discopop_explorer/utils.py | 6 +- discopop_explorer/variable.py | 4 +- .../CodeGenerator/CodeGenerator.py | 14 +- .../CodeGenerator/classes/ContentBuffer.py | 12 +- .../CodeGenerator/classes/Line.py | 2 +- .../classes/UnpackedSuggestion.py | 41 +- discopop_library/GlobalLogger/setup.py | 2 +- .../LineMapping/diff_modifications.py | 4 +- discopop_library/LineMapping/initialize.py | 2 +- discopop_library/LineMapping/save.py | 2 +- .../PatchGenerator/from_json_patterns.py | 2 +- .../PatchGenerator/from_optimizer_output.py | 2 +- .../PatchGenerator/patch_generator.py | 2 +- .../CostModels/CostModel.py | 9 +- .../CostModels/utilities.py | 4 +- .../DataTransfers/DataTransfers.py | 13 +- .../DataTransfers/NewDataTransfers.py | 8 +- .../calculate_configuration_data_movement.py | 2 +- .../DelaunayInterpolatedMicrobench.py | 18 +- .../ExtrapInterpolatedMicrobench.py | 17 +- .../Microbench/Microbench.py | 6 +- .../Microbench/PureDataMicrobench.py | 14 +- .../discopop_optimizer/PETParser/PETParser.py | 6 +- .../RemoveDuplicatedUpdates.py | 4 +- .../Variables/Experiment.py | 11 +- .../Variables/ExperimentUtils.py | 14 +- .../classes/context/ContextObject.py | 22 +- .../classes/nodes/ContextMerge.py | 3 +- .../classes/nodes/ContextNode.py | 3 +- .../classes/nodes/ContextRestore.py | 3 +- .../classes/nodes/ContextSave.py | 3 +- .../classes/nodes/ContextSnapshot.py | 3 +- .../classes/nodes/ContextSnapshotPop.py | 3 +- .../classes/nodes/DeviceSwitch.py | 3 +- .../classes/nodes/FunctionReturn.py | 3 +- .../classes/nodes/FunctionRoot.py | 14 +- .../classes/nodes/GenericNode.py | 22 +- .../discopop_optimizer/classes/nodes/Loop.py | 12 +- .../classes/nodes/SynchronizationTrigger.py | 3 +- .../classes/nodes/Workload.py | 26 +- .../classes/system/Network.py | 14 +- .../classes/system/System.py | 24 +- .../classes/system/devices/CPU.py | 6 +- .../classes/system/devices/Device.py | 6 +- .../classes/system/devices/GPU.py | 10 +- .../classes/system/system_utils.py | 2 +- .../gui/plotting/CostModels.py | 18 +- .../gui/presentation/ChoiceDetails.py | 2 +- .../gui/presentation/OptionTable.py | 6 +- .../gui/widgets/ScrollableFrame.py | 2 +- .../interactive/interactive_optimizer.py | 14 +- .../evaluate_all_decision_combinations.py | 8 +- .../optimization/evolutionary_algorithm.py | 26 +- .../discopop_optimizer/optimization/greedy.py | 4 +- .../discopop_optimizer/optimizer.py | 4 +- .../scheduling/workload_delta.py | 2 +- .../suggestions/importers/do_all.py | 4 +- .../suggestions/importers/reduction.py | 8 +- .../utilities/MOGUtilities.py | 32 +- .../utilities/insert_device_switch_nodes.py | 2 +- .../GlobalOptimization/RandomSamples.py | 8 +- .../utilities/visualization/update_graph.py | 2 +- .../result_classes/OptimizerOutputPattern.py | 8 +- .../do_all/calls/complex/src/FileMapping.txt | 1 + .../do_all/calls/complex/src/code.ll | 780 ++++++++++++++++++ 101 files changed, 1398 insertions(+), 413 deletions(-) create mode 100644 test/end_to_end/do_all/calls/complex/src/FileMapping.txt create mode 100644 test/end_to_end/do_all/calls/complex/src/code.ll diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c3a15ba37..aca972912 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,11 +47,11 @@ jobs: - name: "Run MyPy Type Checker - DiscoPoP Library" run: python -m mypy --config-file=mypy.ini -p discopop_library - - name: "Run MyPy Type Checker - DiscoPoP Profiler - DEPRECATED" - run: python -m mypy --config-file=mypy.ini -p DEPRECATED_discopop_profiler - - - name: "Run MyPy Type Checker - DiscoPoP Wizard - DEPRECATED" - run: python -m mypy --config-file=mypy.ini -p DEPRECATED_discopop_wizard +# - name: "Run MyPy Type Checker - DiscoPoP Profiler - DEPRECATED" +# run: python -m mypy --config-file=mypy.ini -p DEPRECATED_discopop_profiler +# +# - name: "Run MyPy Type Checker - DiscoPoP Wizard - DEPRECATED" +# run: python -m mypy --config-file=mypy.ini -p DEPRECATED_discopop_wizard - name: "Check formatting of DiscoPoP Explorer" run: python -m black -l 120 --check discopop_explorer @@ -59,11 +59,11 @@ jobs: - name: "Check formatting of DiscoPoP Library" run: python -m black -l 120 --check discopop_library - - name: "Check formatting of DiscoPoP Profiler - DEPRECATED" - run: python -m black -l 120 --check DEPRECATED_discopop_profiler - - - name: "Check formatting of DiscoPoP Wizard - DEPRECATED" - run: python -m black -l 120 --check DEPRECATED_discopop_wizard +# - name: "Check formatting of DiscoPoP Profiler - DEPRECATED" +# run: python -m black -l 120 --check DEPRECATED_discopop_profiler +# +# - name: "Check formatting of DiscoPoP Wizard - DEPRECATED" +# run: python -m black -l 120 --check DEPRECATED_discopop_wizard execute_cxx_unit_tests: runs-on: ubuntu-20.04 diff --git a/DEPRECATED_discopop_wizard/screens/widgets/ScrollableText.py b/DEPRECATED_discopop_wizard/screens/widgets/ScrollableText.py index 7f05132ad..775be77e3 100644 --- a/DEPRECATED_discopop_wizard/screens/widgets/ScrollableText.py +++ b/DEPRECATED_discopop_wizard/screens/widgets/ScrollableText.py @@ -37,7 +37,7 @@ def __init__(self, parent_frame): self.text_container["xscrollcommand"] = x_scrollbar.set self.text_container.config(state=tk.DISABLED) - def set_text(self, content: str): + def set_text(self, content: str) -> None: self.text_container.config(state=tk.NORMAL) self.text_container.delete("1.0", tk.END) self.text_container.insert("1.0", content) diff --git a/discopop_explorer/PEGraphX.py b/discopop_explorer/PEGraphX.py index c026a7da0..569250686 100644 --- a/discopop_explorer/PEGraphX.py +++ b/discopop_explorer/PEGraphX.py @@ -19,7 +19,8 @@ from alive_progress import alive_bar # type: ignore from lxml.objectify import ObjectifiedElement # type: ignore -from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType # type:ignore +from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType +from discopop_library.HostpotLoader.HotspotType import HotspotType # type:ignore from .parser import LoopData, readlineToCUIdMap, writelineToCUIdMap, DependenceItem from .variable import Variable @@ -195,12 +196,12 @@ def __init__(self, node_id: NodeID): self.id = node_id self.file_id, self.node_id = parse_id(node_id) - @classmethod - def from_kwargs(cls, node_id: NodeID, **kwargs): - node = cls(node_id) - for key, value in kwargs.items(): - setattr(node, key, value) - return node + # @classmethod + # def from_kwargs(cls, node_id: NodeID, **kwargs) -> Node: + # node = cls(node_id) + # for key, value in kwargs.items(): + # setattr(node, key, value) + # return node def start_position(self) -> LineID: """Start position file_id:line @@ -219,7 +220,7 @@ def end_position(self) -> LineID: """ return LineID(f"{self.file_id}:{self.end_line}") - def contains_line(self, other_line) -> bool: + def contains_line(self, other_line: str) -> bool: if other_line == "GlobalVar" or other_line == "LineNotFound": return False if not ":" in other_line: @@ -380,7 +381,7 @@ def get_exit_cu_ids(self, pet: PEGraphX) -> Set[NodeID]: exit_cu_ids.add(child_cu_id) return exit_cu_ids - def calculate_reachability_pairs(self, pet: PEGraphX): + def calculate_reachability_pairs(self, pet: PEGraphX) -> Dict[NodeID, Set[NodeID]]: reachability_pairs: Dict[NodeID, Set[NodeID]] = dict() # create graph copy and remove all but successor edges copied_graph = pet.g.copy() @@ -614,7 +615,7 @@ class PEGraphX(object): main: Node pos: Dict[Any, Any] - def __init__(self, g: nx.MultiDiGraph, reduction_vars: List[Dict[str, str]], pos): + def __init__(self, g: nx.MultiDiGraph, reduction_vars: List[Dict[str, str]], pos: Dict[Any, Any]): self.g = g self.reduction_vars = reduction_vars for _, node in g.nodes(data="data"): @@ -629,7 +630,7 @@ def from_parsed_input( dependencies_list: List[DependenceItem], loop_data: Dict[str, LoopData], reduction_vars: List[Dict[str, str]], - ): + ) -> PEGraphX: """Constructor for making a PETGraphX from the output of parser.parse_inputs()""" g = nx.MultiDiGraph() print("\tCreating graph...") @@ -766,7 +767,11 @@ def map_static_and_dynamic_dependencies(self): print("Done.") - def calculateFunctionMetadata(self, hotspot_information=None, func_nodes=None) -> None: + def calculateFunctionMetadata( + self, + hotspot_information: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]]] = None, + func_nodes: Optional[List[FunctionNode]] = None, + ) -> None: # store id of parent function in each node # and store in each function node a list of all children ids if func_nodes is None: @@ -1088,7 +1093,7 @@ def subtree_of_type_rec(self, root, visited, type=Node): return res - def __cu_equal__(self, cu_1: Node, cu_2: Node): + def __cu_equal__(self, cu_1: Node, cu_2: Node) -> bool: """Alternative to CUNode.__eq__, bypasses the isinstance-check and relies on MyPy for type safety. :param cu_1: CUNode 1 :param cu_2: CUNode 2 @@ -1358,7 +1363,7 @@ def get_undefined_variables_inside_loop( return vars - def unused_is_first_written_in_loop(self, dep: Dependency, root_loop: Node): + def unused_is_first_written_in_loop(self, dep: Dependency, root_loop: Node) -> bool: """Checks whether a variable is first written inside the current node :param var: diff --git a/discopop_explorer/discopop_explorer.py b/discopop_explorer/discopop_explorer.py index bf62c48f0..69c4c390b 100644 --- a/discopop_explorer/discopop_explorer.py +++ b/discopop_explorer/discopop_explorer.py @@ -171,7 +171,7 @@ def __run( return res -def run(arguments: ExplorerArguments): +def run(arguments: ExplorerArguments) -> None: """Run the discopop_explorer with the given arguments""" logger = logging.getLogger("Explorer") diff --git a/discopop_explorer/generate_Data_CUInst.py b/discopop_explorer/generate_Data_CUInst.py index 96910cc1c..402138250 100644 --- a/discopop_explorer/generate_Data_CUInst.py +++ b/discopop_explorer/generate_Data_CUInst.py @@ -6,6 +6,7 @@ # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. +from io import TextIOWrapper from typing import List, cast, TextIO from .PEGraphX import ( @@ -22,7 +23,7 @@ from .parser import parse_inputs -def __collect_children_ids(pet: PEGraphX, parent_id: NodeID, children_ids: List[NodeID]): +def __collect_children_ids(pet: PEGraphX, parent_id: NodeID, children_ids: List[NodeID]) -> List[NodeID]: if parent_id in children_ids: # this id has already been processed. No need to go through it again return children_ids @@ -104,7 +105,7 @@ def __output_dependencies_of_type( output_file: TextIO, dep_type: DepType, dep_identifier: str, -): +) -> None: """check for and output dependencies of the given type :param pet: PET Graph :param child_id: specific node id, taken from children_ids @@ -131,7 +132,7 @@ def __output_dependencies_of_type( ) -def __search_recursive_calls(pet: PEGraphX, output_file, node: Node): +def __search_recursive_calls(pet: PEGraphX, output_file: TextIOWrapper, node: Node) -> None: if not isinstance(node, CUNode): return for recursive_function_call in node.recursive_function_calls: @@ -165,7 +166,7 @@ def __search_recursive_calls(pet: PEGraphX, output_file, node: Node): output_file.write("\n") -def cu_instantiation_input_cpp(pet: PEGraphX, output_file: str): +def cu_instantiation_input_cpp(pet: PEGraphX, output_file: str) -> None: """translation of CUInstantiationInput.cpp, previously contained in discopop-analyzer/analyzer/src. Wrapper to gather information on recursive function calls for CU Instantiation. :param pet: PET Graph @@ -175,7 +176,7 @@ def cu_instantiation_input_cpp(pet: PEGraphX, output_file: str): __search_recursive_calls(pet, data_cu_inst_file, node) -def wrapper(cu_xml, dep_file, loop_counter_file, reduction_file, output_file): +def wrapper(cu_xml: str, dep_file: str, loop_counter_file: str, reduction_file: str, output_file: str) -> None: """Wrapper to generate the Data_CUInst.txt file, required for the generation of CUInstResult.txt""" # 1. generate PET Graph pet = PEGraphX.from_parsed_input(*parse_inputs(cu_xml, dep_file, loop_counter_file, reduction_file)) diff --git a/discopop_explorer/parser.py b/discopop_explorer/parser.py index 9bbcd9984..3ab39fcb6 100644 --- a/discopop_explorer/parser.py +++ b/discopop_explorer/parser.py @@ -6,6 +6,7 @@ # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. +from io import TextIOWrapper import os import re import warnings @@ -110,7 +111,7 @@ def __map_dummy_nodes(cu_dict): return cu_dict -def __parse_dep_file(dep_fd, output_path: str) -> Tuple[List[DependenceItem], List[LoopData]]: +def __parse_dep_file(dep_fd: TextIOWrapper, output_path: str) -> Tuple[List[DependenceItem], List[LoopData]]: dependencies_list: List[DependenceItem] = [] loop_data_list: List[LoopData] = [] diff --git a/discopop_explorer/pattern_detection.py b/discopop_explorer/pattern_detection.py index a4a78e741..e2767d2de 100644 --- a/discopop_explorer/pattern_detection.py +++ b/discopop_explorer/pattern_detection.py @@ -8,7 +8,7 @@ import json import os import sys -from typing import cast +from typing import Dict, List, Optional, Tuple, cast from alive_progress import alive_bar # type: ignore @@ -16,6 +16,8 @@ build_preprocessed_graph_and_run_detection as detect_tp, ) from discopop_explorer.variable import Variable +from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType +from discopop_library.HostpotLoader.HotspotType import HotspotType from discopop_library.JSONHandler.JSONHandler import read_patterns_from_json_to_json from discopop_library.discopop_optimizer.OptimizationGraph import OptimizationGraph from discopop_library.discopop_optimizer.Variables.Experiment import Experiment @@ -43,7 +45,7 @@ def __init__(self, pet_graph: PEGraphX) -> None: """ self.pet = pet_graph - def __merge(self, loop_type: bool, remove_dummies: bool): + def __merge(self, loop_type: bool, remove_dummies: bool) -> None: """Removes dummy nodes :param loop_type: loops only @@ -63,20 +65,20 @@ def __merge(self, loop_type: bool, remove_dummies: bool): def detect_patterns( self, - project_path, - cu_dict, - dependencies, - loop_data, - reduction_vars, - file_mapping, - cu_inst_result_file, - llvm_cxxfilt_path, - discopop_build_path, - enable_patterns, - enable_task_pattern, - enable_detection_of_scheduling_clauses, - hotspots, - ): + project_path: str, + cu_dict: str, + dependencies: str, + loop_data: str, + reduction_vars: str, + file_mapping: Optional[str], + cu_inst_result_file: Optional[str], + llvm_cxxfilt_path: Optional[str], + discopop_build_path: Optional[str], + enable_patterns: str, + enable_task_pattern: bool, + enable_detection_of_scheduling_clauses: bool, + hotspots: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]]], + ) -> DetectionResult: """Runs pattern discovery on the CU graph""" self.__merge(False, True) self.pet.map_static_and_dynamic_dependencies() @@ -105,6 +107,10 @@ def detect_patterns( # check if task pattern should be enabled if enable_task_pattern: + if cu_inst_result_file is None: + raise ValueError("cu_inst_result_file not specified.") + if file_mapping is None: + raise ValueError("file_mapping not specified.") res.patterns.task = detect_tp( cu_dict, dependencies, diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py index 8d97fdd6b..b49df0244 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py @@ -6,7 +6,7 @@ # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. import sys -from typing import List, Tuple, Dict, Set +from typing import List, Tuple, Dict, Set, cast from discopop_explorer.PEGraphX import EdgeType, CUNode, PEGraphX, NodeID, MemoryRegion from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo @@ -14,6 +14,7 @@ VarName, ) from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Dependency import Dependency +from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.EntryPoint import EntryPoint from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Enums import ( ExitPointPositioning, EntryPointPositioning, @@ -21,6 +22,8 @@ EntryPointType, UpdateType, ) +from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.ExitPoint import ExitPoint +from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Update import Update from discopop_explorer.pattern_detectors.combined_gpu_patterns.prepare_metadata import ( get_dependencies_as_metadata, ) @@ -68,10 +71,10 @@ class CombinedGPURegion(PatternInfo): target_data_regions: Dict[str, List[Tuple[List[NodeID], NodeID, NodeID, str, str]]] # {var: ([contained cu_s], entry_cu, exit_after_cu, meta_entry_line_num, meta_exit_line_num) data_region_entry_points: List[ - Tuple[VarName, NodeID, EntryPointType, str, EntryPointPositioning] + Tuple[str, NodeID, NodeID, EntryPointType, str, EntryPointPositioning] ] # [(var, cu_id, entry_point_type, meta_line_num, positioning)] data_region_exit_points: List[ - Tuple[VarName, NodeID, ExitPointType, str, ExitPointPositioning] + Tuple[str, NodeID, NodeID, ExitPointType, str, ExitPointPositioning] ] # [(var, cu_id, exit_point_type, meta_line_num, positioning)] data_region_depend_in: List[Tuple[VarName, NodeID, str]] # [(var, cu_id, meta_line_num)] data_region_depend_out: List[Tuple[VarName, NodeID, str]] # [(var, cu_id, meta_line_num)] @@ -302,9 +305,9 @@ def __init__(self, pet: PEGraphX, contained_regions: List[GPURegionInfo], projec ) # remove duplicates - updates = remove_duplicates(updates) - entry_points = remove_duplicates(entry_points) - exit_points = remove_duplicates(exit_points) + updates = cast(Set[Update], remove_duplicates(updates)) + entry_points = cast(Set[EntryPoint], remove_duplicates(entry_points)) + exit_points = cast(Set[ExitPoint], remove_duplicates(exit_points)) # join entries updates = join_elements(updates) @@ -354,7 +357,7 @@ def __init__(self, pet: PEGraphX, contained_regions: List[GPURegionInfo], projec def __str__(self): raise NotImplementedError() # used to identify necessity to call to_string() instead - def to_string(self, pet: PEGraphX): + def to_string(self, pet: PEGraphX) -> str: contained_regions_str = "\n" if len(self.contained_regions) > 0 else "" for region in self.contained_regions: region_str = region.to_string(pet) @@ -453,7 +456,7 @@ def find_combinations_within_function_body( def find_true_successor_combinations( - pet, intra_function_combinations: List[Tuple[CombinedGPURegion, CombinedGPURegion]] + pet: PEGraphX, intra_function_combinations: List[Tuple[CombinedGPURegion, CombinedGPURegion]] ) -> List[Tuple[CombinedGPURegion, CombinedGPURegion]]: """Check for combinations options without branching inbetween. As a result, both regions will always be executed in succession.""" @@ -462,7 +465,9 @@ def find_true_successor_combinations( # a true successor relation exists, if every successor path outgoing from any child of region_1 arrives at region_2 for region_1, region_2 in intra_function_combinations: true_successors = True - queue: List[CUNode] = pet.direct_children(pet.node_at(region_1.contained_regions[0].node_id)) + queue: List[CUNode] = cast( + List[CUNode], pet.direct_children(pet.node_at(region_1.contained_regions[0].node_id)) + ) visited: List[CUNode] = [] while queue: current_node: CUNode = queue.pop() @@ -479,7 +484,7 @@ def find_true_successor_combinations( else: # end of the function's body not yet reached, continue searching # add successors to queue - queue += [succ for succ in successors if succ not in visited] + queue += [cast(CUNode, succ) for succ in successors if succ not in visited] if true_successors: result.append((region_1, region_2)) return result diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py index 083f266f0..7ad1ed032 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py @@ -118,7 +118,9 @@ def join(self, other): self.memory_regions.update(other.memory_regions) self.dependencies.update(other.dependencies) - def get_as_metadata(self, pet: PEGraphX, project_folder_path: str): + def get_as_metadata( + self, pet: PEGraphX, project_folder_path: str + ) -> Tuple[str, NodeID, NodeID, EntryPointType, str, EntryPointPositioning]: # get type of mapped variables var_names_types_and_sizes: List[Tuple[VarName, str, int]] = [] for var_name in self.var_names: @@ -148,11 +150,11 @@ def get_as_metadata(self, pet: PEGraphX, project_folder_path: str): else: modified_var_names = [(vn + "[:]" if "**" in t else vn) for vn, t, s in var_names_types_and_sizes] - return [ + return ( ",".join(modified_var_names), self.source_cu_id, self.sink_cu_id, self.entry_point_type, self.pragma_line, self.entry_point_positioning, - ] + ) diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py index c2729672a..ed8388e9a 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py @@ -116,7 +116,9 @@ def join(self, other): self.memory_regions.update(other.memory_regions) self.dependencies.update(other.dependencies) - def get_as_metadata(self, pet: PEGraphX, project_folder_path: str): + def get_as_metadata( + self, pet: PEGraphX, project_folder_path: str + ) -> Tuple[str, NodeID, NodeID, ExitPointType, str, ExitPointPositioning]: # get type of mapped variables var_names_types_and_sizes: List[Tuple[VarName, str, int]] = [] for var_name in self.var_names: @@ -146,11 +148,11 @@ def get_as_metadata(self, pet: PEGraphX, project_folder_path: str): else: modified_var_names = [(vn + "[:]" if "**" in t else vn) for vn, t, s in var_names_types_and_sizes] - return [ + return ( ",".join(modified_var_names), self.source_cu_id, self.sink_cu_id, self.exit_point_type, self.pragma_line, self.exit_point_positioning, - ] + ) diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py index 98bc650f9..d68561e59 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py @@ -8,7 +8,7 @@ import os from typing import Set, Dict, cast, Optional, List, Tuple -from discopop_explorer.PEGraphX import PEGraphX, NodeID, MemoryRegion +from discopop_explorer.PEGraphX import LineID, PEGraphX, NodeID, MemoryRegion from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, ) @@ -141,28 +141,32 @@ def __hash__(self): ) ) - def get_position_identifier(self): + def get_position_identifier(self) -> Tuple[NodeID, NodeID, UpdateType]: # used to join multiple elements if self.asynchronous_possible: + if self.asynchronous_source_cu_id is None: + raise ValueError("Asynchronous_source_cu_id is None") return (self.sink_cu_id, self.asynchronous_source_cu_id, self.update_type) else: return (self.sink_cu_id, self.synchronous_source_cu_id, self.update_type) - def join(self, other): + def join(self, other: Update) -> None: self.variable_names.update(other.variable_names) self.memory_regions.update(other.memory_regions) self.dependencies.update(other.dependencies) - def get_as_metadata_using_memory_regions(self, pet: PEGraphX): - return [ + def get_as_metadata_using_memory_regions(self, pet: PEGraphX) -> Tuple[NodeID, NodeID, UpdateType, str, LineID]: + return ( self.synchronous_source_cu_id, self.sink_cu_id, self.update_type, str(self.memory_regions), pet.node_at(self.synchronous_source_cu_id).end_position(), - ] + ) - def get_as_metadata_using_variable_names(self, pet: PEGraphX, project_folder_path: str): + def get_as_metadata_using_variable_names( + self, pet: PEGraphX, project_folder_path: str + ) -> Tuple[NodeID, NodeID, UpdateType, str, LineID]: # get type of mapped variables var_names_types_and_sizes: List[Tuple[VarName, str, int]] = [] for var_name in self.variable_names: @@ -212,15 +216,17 @@ def get_as_metadata_using_variable_names(self, pet: PEGraphX, project_folder_pat # updating inbetween both CUs should be a safe fallback update_position = pet.node_at(self.sink_cu_id).start_position() - return [ + return ( self.synchronous_source_cu_id, self.sink_cu_id, self.update_type, ",".join(modified_var_names), update_position, - ] + ) - def get_as_metadata_using_variable_names_and_memory_regions(self, pet: PEGraphX, project_folder_path: str): + def get_as_metadata_using_variable_names_and_memory_regions( + self, pet: PEGraphX, project_folder_path: str + ) -> Tuple[NodeID, NodeID, UpdateType, str, LineID]: # get type of mapped variables var_names_types_and_sizes: List[Tuple[VarName, str, int]] = [] for var_name in self.variable_names: @@ -253,19 +259,19 @@ def get_as_metadata_using_variable_names_and_memory_regions(self, pet: PEGraphX, else: modified_var_names = [(vn + "[:]" if "**" in t else vn) for vn, t, s in var_names_types_and_sizes] - return [ + return ( self.synchronous_source_cu_id, self.sink_cu_id, self.update_type, str(modified_var_names) + "/" + str(self.memory_regions), pet.node_at(self.synchronous_source_cu_id).end_position(), - ] + ) def convert_memory_regions_to_variable_names( self, pet: PEGraphX, memory_regions_to_functions_and_variables: Dict[MemoryRegion, Dict[NodeID, Set[VarName]]], - ): + ) -> None: self.variable_names = set() parent_function_id = pet.get_parent_function(pet.node_at(self.synchronous_source_cu_id)).id diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/combined_gpu_pattern_detector.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/combined_gpu_pattern_detector.py index 2bac17340..0137c5140 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/combined_gpu_pattern_detector.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/combined_gpu_pattern_detector.py @@ -13,9 +13,11 @@ from discopop_explorer.pattern_detectors.combined_gpu_patterns.CombinedGPURegions import ( find_combined_gpu_regions, ) +from discopop_explorer.pattern_detectors.simple_gpu_patterns.GPURegions import GPURegionInfo +from discopop_library.result_classes.DetectionResult import DetectionResult -def run_detection(pet: PEGraphX, res, project_folder_path: str) -> List[PatternInfo]: +def run_detection(pet: PEGraphX, res: DetectionResult, project_folder_path: str) -> List[PatternInfo]: """Search for combined gpu patterns :param pet: PET graph @@ -24,6 +26,8 @@ def run_detection(pet: PEGraphX, res, project_folder_path: str) -> List[PatternI """ # construct Combined GPU Regions - combined_gpu_regions = find_combined_gpu_regions(pet, res.simple_gpu, project_folder_path) + combined_gpu_regions = find_combined_gpu_regions( + pet, cast(List[GPURegionInfo], res.patterns.simple_gpu), project_folder_path + ) return cast(List[PatternInfo], combined_gpu_regions) diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py index 3d1a90132..8de5648e5 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py @@ -6,16 +6,17 @@ # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. -from typing import Tuple, Dict, Set, cast +from typing import List, Tuple, Dict, Set, cast from discopop_explorer.PEGraphX import EdgeType, DepType, PEGraphX, NodeID, CUNode, MemoryRegion from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, ) +from discopop_explorer.pattern_detectors.simple_gpu_patterns.GPURegions import GPURegionInfo def get_written_and_read_memory_regions_by_cu( - contained_regions, pet: PEGraphX + contained_regions: List[GPURegionInfo], pet: PEGraphX ) -> Tuple[Dict[NodeID, Set[MemoryRegion]], Dict[NodeID, Set[MemoryRegion]]]: all_function_cu_ids: Set[NodeID] = set() for region in contained_regions: @@ -67,7 +68,7 @@ def get_written_and_read_memory_regions_by_cu( def get_cu_and_varname_to_memory_regions( - contained_regions, pet: PEGraphX, written_memory_regions_by_cu: Dict[NodeID, Set[MemoryRegion]] + contained_regions: List[GPURegionInfo], pet: PEGraphX, written_memory_regions_by_cu: Dict[NodeID, Set[MemoryRegion]] ) -> Dict[NodeID, Dict[VarName, Set[MemoryRegion]]]: # dict -> {Cu_ID: {var_name: [memory regions]}} result_dict: Dict[NodeID, Dict[VarName, Set[MemoryRegion]]] = dict() diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py index b0e6d4dc5..0fd71f1b0 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py @@ -21,6 +21,7 @@ Dependency, FunctionNode, ) +from discopop_explorer.pattern_detectors.combined_gpu_patterns.CombinedGPURegions import CombinedGPURegion from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, ) @@ -30,7 +31,9 @@ ) -def populate_live_data(comb_gpu_reg, pet: PEGraphX, ignore_update_instructions=False) -> Dict[VarName, List[NodeID]]: +def populate_live_data( + comb_gpu_reg: CombinedGPURegion, pet: PEGraphX, ignore_update_instructions: bool = False +) -> Dict[VarName, List[NodeID]]: """calculate List of cu-id's in the combined region for each variable in which the respective data is live. The gathered information is used for the optimization / creation of data mapping instructions afterwards. """ @@ -56,13 +59,14 @@ def populate_live_data(comb_gpu_reg, pet: PEGraphX, ignore_update_instructions=F if not ignore_update_instructions: # populate liveness sets based on update instructions - for source_id, sink_id, update_type, var, meta_line_num in comb_gpu_reg.update_instructions: - if var not in liveness: - liveness[var] = [] + for source_id, sink_id, update_type, varname_str, meta_line_num in comb_gpu_reg.update_instructions: + varname: VarName = VarName(varname_str) + if varname not in liveness: + liveness[varname] = [] if update_type == UpdateType.TO_DEVICE: - liveness[var].append(sink_id) + liveness[varname].append(sink_id) elif update_type == UpdateType.FROM_DEVICE: - liveness[var].append(source_id) + liveness[varname].append(source_id) else: raise ValueError("Unsupported Update type: ", update_type) @@ -266,7 +270,7 @@ def extend_data_lifespan( def calculate_host_liveness( - comb_gpu_reg, + comb_gpu_reg: CombinedGPURegion, pet: PEGraphX, ) -> Dict[VarName, List[Tuple[NodeID, Set[MemoryRegion]]]]: """ diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py index c99721207..8d29abef6 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py @@ -9,6 +9,7 @@ from typing import Dict, List, Tuple, Set, Optional from discopop_explorer.PEGraphX import PEGraphX, EdgeType, NodeID, CUNode, MemoryRegion +from discopop_explorer.pattern_detectors.combined_gpu_patterns.CombinedGPURegions import CombinedGPURegion global_write_unique_id = 0 @@ -39,7 +40,7 @@ def initialize_writes( def propagate_writes( - comb_gpu_reg, pet: PEGraphX, writes: Dict[MemoryRegion, Set[Tuple[NodeID, Optional[int]]]] + comb_gpu_reg: CombinedGPURegion, pet: PEGraphX, writes: Dict[MemoryRegion, Set[Tuple[NodeID, Optional[int]]]] ) -> Dict[MemoryRegion, Set[Tuple[NodeID, Optional[int]]]]: """propagate writes to parents. propagate writes to successors and their children. diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py index 4ee2fc68a..22d646871 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py @@ -23,6 +23,7 @@ Dependency, FunctionNode, ) +from discopop_explorer.pattern_detectors.combined_gpu_patterns.CombinedGPURegions import CombinedGPURegion from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Enums import UpdateType from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Update import Update @@ -131,7 +132,7 @@ def find_required_updates(self, pet: PEGraphX, new_device_id: int) -> Set[Tuple[ return required_updates - def synchronize_states(self, new_device_id: int): + def synchronize_states(self, new_device_id: int) -> None: overlapping_mem_reg = [ mem_reg for mem_reg in self.seen_writes_by_device[self.device_id] @@ -145,7 +146,9 @@ def synchronize_states(self, new_device_id: int): print("SYNCHRONIZED: ", mem_reg, (ident, origin), file=sys.stderr) self.seen_writes_by_device[new_device_id][mem_reg].add((ident, origin)) - def request_updates_from_other_devices(self, pet, new_device_id: int) -> Set[Tuple[MemoryRegion, int, int, NodeID]]: + def request_updates_from_other_devices( + self, pet: PEGraphX, new_device_id: int + ) -> Set[Tuple[MemoryRegion, int, int, NodeID]]: required_updates: Set[Tuple[MemoryRegion, int, int, NodeID]] = set() to_be_removed = set() for mem_reg in self.seen_writes_by_device[new_device_id]: @@ -198,7 +201,7 @@ def update_to( self, pet: PEGraphX, next_cu_id: NodeID, - comb_gpu_reg, + comb_gpu_reg: CombinedGPURegion, writes_by_device: Dict[int, Dict[NodeID, Dict[MemoryRegion, Set[Optional[int]]]]], ) -> Set[Update]: print("UPDATE TO: ", next_cu_id, file=sys.stderr) @@ -287,14 +290,14 @@ def update_to( return required_updates -def get_device_id(comb_gpu_reg, cu_id: NodeID) -> int: +def get_device_id(comb_gpu_reg: CombinedGPURegion, cu_id: NodeID) -> int: if cu_id in comb_gpu_reg.device_cu_ids: return 1 return 0 -def __identify_merge_node(pet, successors: List[NodeID]) -> Optional[NodeID]: - def check_validity_of_potential_merge_node(node_id: NodeID): +def __identify_merge_node(pet: PEGraphX, successors: List[NodeID]) -> Optional[NodeID]: + def check_validity_of_potential_merge_node(node_id: NodeID) -> bool: # return True if the given node is a valid merge node. # return False otherwise. # do not allow return BB's as merge nodes, since this would be trivially true for every path split @@ -366,7 +369,7 @@ def check_validity_of_potential_merge_node(node_id: NodeID): def identify_updates( - comb_gpu_reg, + comb_gpu_reg: CombinedGPURegion, pet: PEGraphX, writes_by_device: Dict[int, Dict[NodeID, Dict[MemoryRegion, Set[Optional[int]]]]], unrolled_function_graph: MultiDiGraph, @@ -435,7 +438,7 @@ def get_update_type(from_device_id: int, to_device_id: int) -> UpdateType: def __calculate_updates( pet: PEGraphX, - comb_gpu_reg, + comb_gpu_reg: CombinedGPURegion, context: Context, cur_node_id: NodeID, writes_by_device: Dict[int, Dict[NodeID, Dict[MemoryRegion, Set[Optional[int]]]]], @@ -518,7 +521,7 @@ def __calculate_updates( return identified_updates -def create_circle_free_function_graphs(pet: PEGraphX, add_dummy_node=True): +def create_circle_free_function_graphs(pet: PEGraphX, add_dummy_node: bool = True) -> Dict[FunctionNode, MultiDiGraph]: """Remove loops from the CUGraph by unrolling loops in the successor graphs of each function.""" import networkx as nx @@ -728,7 +731,7 @@ def add_accesses_from_called_functions( def identify_updates_in_unrolled_function_graphs( - comb_gpu_reg, + comb_gpu_reg: CombinedGPURegion, pet: PEGraphX, writes_by_device: Dict[int, Dict[NodeID, Dict[MemoryRegion, Set[Optional[int]]]]], unrolled_function_graphs: Dict[FunctionNode, MultiDiGraph], diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py index 35d4b19b7..944b1b97d 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py @@ -337,7 +337,9 @@ def extend_region_liveness_using_unrolled_functions( return liveness -def remove_duplicates(target_set: Union[Set[Update], Set[EntryPoint], Set[ExitPoint]]): +def remove_duplicates( + target_set: Union[Set[Update], Set[EntryPoint], Set[ExitPoint]] +) -> Union[Set[Update], Set[EntryPoint], Set[ExitPoint]]: to_be_removed = [] for element_1 in target_set: for element_2 in target_set: diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py index f1717b109..eac85d82d 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py @@ -47,7 +47,7 @@ def prepare_liveness_metadata( liveness: Dict[MemoryRegion, List[NodeID]], writes: Dict[MemoryRegion, Set[Tuple[NodeID, Optional[int]]]], meta_liveness: Dict[MemoryRegion, List[str]], -): +) -> Dict[MemoryRegion, List[str]]: for mem_reg in liveness: for cu_id in liveness[mem_reg]: if mem_reg not in meta_liveness: diff --git a/discopop_explorer/pattern_detectors/do_all_detector.py b/discopop_explorer/pattern_detectors/do_all_detector.py index 3e38fa573..2cf46a9c2 100644 --- a/discopop_explorer/pattern_detectors/do_all_detector.py +++ b/discopop_explorer/pattern_detectors/do_all_detector.py @@ -7,10 +7,11 @@ # directory for details. import sys from multiprocessing import Pool -from typing import List, Dict, Set, Tuple, cast +from typing import List, Dict, Optional, Set, Tuple, cast import warnings -from alive_progress import alive_bar # type: ignore +from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType +from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore from .PatternInfo import PatternInfo from .reduction_detector import ReductionInfo @@ -71,7 +72,11 @@ def __str__(self): global_pet = None -def run_detection(pet: PEGraphX, hotspots, reduction_info: List[ReductionInfo]) -> List[DoAllInfo]: +def run_detection( + pet: PEGraphX, + hotspots: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]]], + reduction_info: List[ReductionInfo], +) -> List[DoAllInfo]: """Search for do-all loop pattern :param pet: PET graph @@ -376,7 +381,7 @@ def __old_detect_do_all(pet: PEGraphX, root_loop: CUNode) -> bool: return True -def __calculate_nesting_level(pet: PEGraphX, root_loop: LoopNode, cu_node_id: str): +def __calculate_nesting_level(pet: PEGraphX, root_loop: LoopNode, cu_node_id: str) -> int: potential_parents = [(cu_node_id, -1)] # -1 to offset the initialization with cu_node_id while True: if len(potential_parents) == 0: @@ -391,7 +396,7 @@ def __calculate_nesting_level(pet: PEGraphX, root_loop: LoopNode, cu_node_id: st potential_parents.append((in_child_edge[0], nesting_level + 1)) -def __get_parent_loops(pet: PEGraphX, root_loop: LoopNode): +def __get_parent_loops(pet: PEGraphX, root_loop: LoopNode) -> List[LineID]: """duplicates exists: do_all_detector <-> reduction_detector !""" parents: List[NodeID] = [] queue = [root_loop.id] diff --git a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py index d02ab86f6..929d0b4b5 100644 --- a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py +++ b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py @@ -10,7 +10,8 @@ import math from typing import Dict, List, Tuple, Optional, cast -from alive_progress import alive_bar # type: ignore +from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType +from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore from .PatternInfo import PatternInfo from ..PEGraphX import FunctionNode, LoopNode, NodeID, PEGraphX, Node, EdgeType @@ -78,7 +79,9 @@ def __str__(self): global_pet = None -def run_detection(pet: PEGraphX, hotspots) -> List[GDInfo]: +def run_detection( + pet: PEGraphX, hotspots: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]]] +) -> List[GDInfo]: """Detects geometric decomposition :param pet: PET graph diff --git a/discopop_explorer/pattern_detectors/pipeline_detector.py b/discopop_explorer/pattern_detectors/pipeline_detector.py index de70de80f..e34ed388a 100644 --- a/discopop_explorer/pattern_detectors/pipeline_detector.py +++ b/discopop_explorer/pattern_detectors/pipeline_detector.py @@ -7,9 +7,10 @@ # directory for details. -from typing import List, Tuple, Dict, Set, cast +from typing import List, Optional, Tuple, Dict, Set, cast -from alive_progress import alive_bar # type: ignore +from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType +from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore from .PatternInfo import PatternInfo from ..PEGraphX import ( @@ -29,7 +30,13 @@ class PipelineStage(object): - def __init__(self, pet: PEGraphX, node: Node, in_dep, out_dep): + def __init__( + self, + pet: PEGraphX, + node: Node, + in_dep: List[Tuple[NodeID, NodeID, Dependency]], + out_dep: List[Tuple[NodeID, NodeID, Dependency]], + ): self.node = node.id self.startsAtLine = node.start_position() self.endsAtLine = node.end_position() @@ -84,7 +91,7 @@ def __init__(self, pet: PEGraphX, node: Node): self.stages = [self.__output_stage(s) for s in self._stages] - def __in_dep(self, node: Node): + def __in_dep(self, node: Node) -> List[Tuple[NodeID, NodeID, Dependency]]: raw: List[Tuple[NodeID, NodeID, Dependency]] = [] for n in self._pet.subtree_of_type(node, CUNode): raw.extend((s, t, d) for s, t, d in self._pet.out_edges(n.id, EdgeType.DATA) if d.dtype == DepType.RAW) @@ -95,7 +102,7 @@ def __in_dep(self, node: Node): return [dep for dep in raw if dep[1] in [n.id for n in nodes_before]] - def __out_dep(self, node: Node): + def __out_dep(self, node: Node) -> List[Tuple[NodeID, NodeID, Dependency]]: raw: List[Tuple[NodeID, NodeID, Dependency]] = [] for n in self._pet.subtree_of_type(node, CUNode): raw.extend((s, t, d) for s, t, d in self._pet.in_edges(n.id, EdgeType.DATA) if d.dtype == DepType.RAW) @@ -148,7 +155,9 @@ def is_pipeline_subnode(root: Node, current: Node, children_start_lines: List[Li global_pet = None -def run_detection(pet: PEGraphX, hotspots) -> List[PipelineInfo]: +def run_detection( + pet: PEGraphX, hotspots: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]]] +) -> List[PipelineInfo]: """Search for pipeline pattern on all the loops in the graph except for doall loops @@ -162,8 +171,6 @@ def run_detection(pet: PEGraphX, hotspots) -> List[PipelineInfo]: global_pet = pet result: List[PipelineInfo] = [] - children_cache: Dict[Node, List[Node]] = dict() - dependency_cache: Dict[Tuple[Node, Node], Set[Node]] = dict() nodes = pet.all_nodes(LoopNode) nodes = cast(List[LoopNode], filter_for_hotspots(pet, cast(List[Node], nodes), hotspots)) @@ -202,13 +209,11 @@ def __check_node(param_tuple): return local_result -def __detect_pipeline(pet: PEGraphX, root: Node, children_cache=None, dep_cache=None) -> float: +def __detect_pipeline(pet: PEGraphX, root: Node) -> float: """Calculate pipeline value for node :param pet: PET graph :param root: current node - :param children_cache: used to cache intermediate children - :param dep_cache: used to cache intermediate dependencies :return: Pipeline scalar value """ diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index 3afc2494d..24535f357 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -8,10 +8,11 @@ from multiprocessing import Pool -from typing import List, cast, Set, Tuple +from typing import Dict, List, Optional, cast, Set, Tuple import warnings -from alive_progress import alive_bar # type: ignore +from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType +from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore from .PatternInfo import PatternInfo from ..PEGraphX import ( @@ -66,7 +67,9 @@ def __str__(self): global_pet = None -def run_detection(pet: PEGraphX, hotspots) -> List[ReductionInfo]: +def run_detection( + pet: PEGraphX, hotspots: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]]] +) -> List[ReductionInfo]: """Search for reduction pattern :param pet: PET graph @@ -141,7 +144,7 @@ def __detect_reduction(pet: PEGraphX, root: LoopNode) -> bool: if is_reduction_var(root.start_position(), v.name, pet.reduction_vars) # and "**" not in v.type --> replaced by check for array reduction ] - reduction_var_names = [v.name for v in reduction_vars] + reduction_var_names = cast(List[str], [v.name for v in reduction_vars]) fp, p, lp, s, r = classify_loop_variables(pet, root) # get parents of loop @@ -315,7 +318,7 @@ def __check_loop_dependencies( return False -def __get_parent_loops(pet: PEGraphX, root_loop: LoopNode): +def __get_parent_loops(pet: PEGraphX, root_loop: LoopNode) -> List[LineID]: """duplicates exists: do_all_detector <-> reduction_detector !""" parents: List[NodeID] = [] queue = [root_loop.id] diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py index 900e38e44..0276e4d9b 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py @@ -42,6 +42,7 @@ ) from discopop_explorer.variable import Variable from discopop_library.MemoryRegions.utils import get_sizes_of_memory_regions +from discopop_library.result_classes.DetectionResult import DetectionResult from .GPUMemory import getCalledFunctions, map_node """ @@ -180,8 +181,8 @@ def __init__( self, pet: PEGraphX, nodeID: NodeID, - startLine, - endLine, + startLine: LineID, + endLine: LineID, iterationCount: int, project_folder_path: str, reduction_vars: Optional[List[Variable]] = None, @@ -240,7 +241,7 @@ def to_string(self, pet: PEGraphX) -> str: f"OpenMP constructs: {construct_str}\n" ) - def save_omp_constructs(self, pet: PEGraphX, project_folder_path: str): + def save_omp_constructs(self, pet: PEGraphX, project_folder_path: str) -> None: """Save OpenMP constructs such that they are included in the exported JSON file.""" constructs = self.__get_constructs(pet, project_folder_path) self.constructs = constructs @@ -633,7 +634,7 @@ def getNextLoop(self, pet: PEGraphX, node_id: NodeID) -> None: if children.end_line > endLine: endLine = children.end_line - def setCollapseClause(self, pet: PEGraphX, node_id: NodeID, res): + def setCollapseClause(self, pet: PEGraphX, node_id: NodeID, res: DetectionResult) -> None: """ :param node_id: diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py index c6ca69482..077ceaf4d 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py @@ -72,7 +72,7 @@ def __init__( def __str__(self): raise NotImplementedError() # used to identify necessity to call to_string() instead - def to_string(self, pet: PEGraphX): + def to_string(self, pet: PEGraphX) -> str: contained_loops_str = "\n" if len(self.contained_loops) > 0 else "" for loop in self.contained_loops: loop_str = loop.to_string(pet) @@ -346,8 +346,8 @@ def old_mapData(self) -> None: lastNodeID = self.cascadingLoopsInRegions[i][t] fn = map_node(self.pet, firstNodeID) ln = map_node(self.pet, lastNodeID) - start = fn.start_line - end = ln.end_line + start = fn.start_position() + end = ln.end_position() gpuRegionLoop = GPULoopPattern(self.pet, firstNodeID, start, end, 1000, self.project_folder_path) visitedVars: Set[Variable] = set() while t >= 0: diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py index 9abd89020..28edc22ea 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py @@ -10,7 +10,7 @@ from alive_progress import alive_bar # type: ignore -from discopop_explorer.PEGraphX import PEGraphX, LoopNode +from discopop_explorer.PEGraphX import LineID, PEGraphX, LoopNode from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.simple_gpu_patterns.GPULoop import GPULoopPattern from discopop_explorer.pattern_detectors.simple_gpu_patterns.GPURegions import ( @@ -18,9 +18,10 @@ GPURegionInfo, ) from discopop_explorer.variable import Variable +from discopop_library.result_classes.DetectionResult import DetectionResult -def run_detection(pet: PEGraphX, res, project_folder_path: str) -> List[PatternInfo]: +def run_detection(pet: PEGraphX, res: DetectionResult, project_folder_path: str) -> List[PatternInfo]: """Search for do-all loop pattern :param pet: PET graph @@ -46,8 +47,8 @@ def run_detection(pet: PEGraphX, res, project_folder_path: str) -> List[PatternI gpulp = GPULoopPattern( pet, node.id, - node.start_line, - node.end_line, + LineID(str(node.file_id) + ":" + str(node.start_line)), + LineID(str(node.file_id) + ":" + str(node.end_line)), node.loop_iterations, project_folder_path, reduction_vars, diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/utils.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/utils.py index c837adf32..168651770 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/utils.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/utils.py @@ -6,10 +6,11 @@ # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. +from discopop_explorer.PEGraphX import NodeID from discopop_explorer.pattern_detectors.simple_gpu_patterns.GPULoop import GPULoopPattern -def sort_by_nodeID(e: GPULoopPattern): +def sort_by_nodeID(e: GPULoopPattern) -> NodeID: """used to sort a list of gpu patterns by their node ids :return: diff --git a/discopop_explorer/pattern_detectors/task_parallelism/alias_detection.py b/discopop_explorer/pattern_detectors/task_parallelism/alias_detection.py index 203a8348f..736796c80 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/alias_detection.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/alias_detection.py @@ -274,7 +274,7 @@ def __get_function_information(cu_xml: str) -> List[Dict[str, Any]]: return function_information -def __create_statements_file(file_mapping: str, output_file: str, application_path: str): +def __create_statements_file(file_mapping: str, output_file: str, application_path: str) -> None: """Wrapper to start getStatements application for each source code file in file_mapping :param file_mapping: path to file_mapping file :param output_file: path to output file diff --git a/discopop_explorer/pattern_detectors/task_parallelism/classes.py b/discopop_explorer/pattern_detectors/task_parallelism/classes.py index b2ad620a9..c1246c828 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/classes.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/classes.py @@ -9,7 +9,7 @@ from enum import Enum from typing import List, Optional -from discopop_explorer.PEGraphX import Node, MWType, PEGraphX +from discopop_explorer.PEGraphX import LineID, Node, MWType, PEGraphX from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo @@ -22,8 +22,8 @@ class Task(object): nodes: List[Node] child_tasks: List["Task"] - start_line: str - end_line: str + start_line: LineID + end_line: LineID def __init__(self, pet: PEGraphX, node: Node): self.node_id = node.id @@ -47,7 +47,7 @@ def __init__(self, pet: PEGraphX, node: Node): self.workload = 0 self.child_tasks = [] - def aggregate(self, other: "Task"): + def aggregate(self, other: "Task") -> None: """Aggregates given task into current task :param other: task to aggregate @@ -70,7 +70,16 @@ class TPIType(Enum): class TaskParallelismInfo(PatternInfo): """Class, that contains task parallelism detection result""" - def __init__(self, node: Node, type: TPIType, pragma, pragma_line, first_private, private, shared): + def __init__( + self, + node: Node, + type: TPIType, + pragma: List[str], + pragma_line: str, + first_private: List[str], + private: List[str], + shared: List[str], + ): """ :param node: node, where task parallelism was detected :param type: type of the suggestion (task, taskwait, taskloop) @@ -123,7 +132,7 @@ def __str__(self): class ParallelRegionInfo(PatternInfo): """Class, that contains parallel region info.""" - def __init__(self, node: Node, type: TPIType, region_start_line, region_end_line): + def __init__(self, node: Node, type: TPIType, region_start_line: LineID, region_end_line: LineID): PatternInfo.__init__(self, node) self.region_start_line = region_start_line self.region_end_line = region_end_line diff --git a/discopop_explorer/pattern_detectors/task_parallelism/filter.py b/discopop_explorer/pattern_detectors/task_parallelism/filter.py index bfdfea80d..eb795c54e 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/filter.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/filter.py @@ -8,7 +8,7 @@ from typing import List, Dict, cast, Optional, Union -from discopop_explorer.PEGraphX import CUNode, NodeType, EdgeType, Node, PEGraphX +from discopop_explorer.PEGraphX import CUNode, LineID, NodeType, EdgeType, Node, PEGraphX from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.task_parallelism.classes import ( TaskParallelismInfo, @@ -22,6 +22,7 @@ check_reachability, ) from discopop_explorer.utils import is_loop_index2 +from discopop_library.discopop_optimizer.classes.nodes.FunctionRoot import FunctionRoot def filter_data_sharing_clauses( @@ -38,7 +39,9 @@ def filter_data_sharing_clauses( return suggestions -def __filter_data_sharing_clauses_suppress_shared_loop_index(pet: PEGraphX, suggestions: List[PatternInfo]): +def __filter_data_sharing_clauses_suppress_shared_loop_index( + pet: PEGraphX, suggestions: List[PatternInfo] +) -> List[PatternInfo]: """Removes clauses for shared loop indices. :param pet: PET graph :param suggestions: List[PatternInfo] @@ -120,7 +123,9 @@ def __filter_data_sharing_clauses_by_function( return suggestions -def __filter_shared_clauses(suggestion: TaskParallelismInfo, parent_function, var_def_line_dict: Dict[str, List[str]]): +def __filter_shared_clauses( + suggestion: TaskParallelismInfo, parent_function: Node, var_def_line_dict: Dict[str, List[str]] +) -> None: """helper function for filter_data_sharing_clauses_by_function. Filters shared clauses. :param suggestion: Suggestion to be checked @@ -153,7 +158,9 @@ def __filter_shared_clauses(suggestion: TaskParallelismInfo, parent_function, va suggestion.shared = [v for v in suggestion.shared if not v.replace(".addr", "") in to_be_removed] -def __filter_private_clauses(suggestion: TaskParallelismInfo, parent_function, var_def_line_dict: Dict[str, List[str]]): +def __filter_private_clauses( + suggestion: TaskParallelismInfo, parent_function: Node, var_def_line_dict: Dict[str, List[str]] +) -> None: """helper function for filter_data_sharing_clauses_by_function. Filters private clauses. :param suggestion: Suggestion to be checked @@ -191,8 +198,8 @@ def __filter_private_clauses(suggestion: TaskParallelismInfo, parent_function, v def __filter_firstprivate_clauses( - suggestion: TaskParallelismInfo, parent_function, var_def_line_dict: Dict[str, List[str]] -): + suggestion: TaskParallelismInfo, parent_function: Node, var_def_line_dict: Dict[str, List[str]] +) -> None: """helper function for filter_data_sharing_clauses_by_function. Filters firstprivate clauses. :param suggestion: Suggestion to be checked @@ -221,7 +228,9 @@ def __filter_firstprivate_clauses( suggestion.first_private = [v for v in suggestion.first_private if not v.replace(".addr", "") in to_be_removed] -def __reverse_reachable_w_o_breaker(pet: PEGraphX, root: Node, target: Node, breaker_cu: Node, visited: List[Node]): +def __reverse_reachable_w_o_breaker( + pet: PEGraphX, root: Node, target: Node, breaker_cu: Node, visited: List[Node] +) -> bool: """Helper function for filter_data_sharing_clauses_by_scope. Checks if target is reachable by traversing the successor graph in reverse, starting from root, without visiting breaker_cu. @@ -289,9 +298,9 @@ def __filter_sharing_clause( pet: PEGraphX, suggestion: TaskParallelismInfo, var_def_line_dict: Dict[str, List[str]], - parent_function_cu, + parent_function_cu: Node, target_clause_list: str, -): +) -> None: """Helper function for filter_data_sharing_clauses_by_scope. Filters a given suggestions private, firstprivate or shared variables list, depending on the specific value of target_clause_list. @@ -377,8 +386,8 @@ def remove_useless_barrier_suggestions( # remove suggested barriers which are no descendants of relevant functions result_suggestions += task_suggestions for tws in taskwait_suggestions: - tws_line_number = tws.pragma_line - tws_line_number = tws_line_number[tws_line_number.index(":") + 1 :] + tws_line_id = tws.pragma_line + tws_line_number = tws_line_id[tws_line_id.index(":") + 1 :] for rel_func_body in relevant_function_bodies.keys(): if check_reachability(pet, tws._node, rel_func_body, [EdgeType.CHILD]): # remove suggested barriers where line number smaller than diff --git a/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py b/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py index 190490e30..d041fb8a2 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py @@ -8,7 +8,7 @@ import copy import os -from typing import List +from typing import Any, List from lxml import objectify, etree # type: ignore @@ -347,7 +347,7 @@ def __add_parent_id_to_children(parsed_cu, parent): parent_function.childrenNodes._setText(parent_function.childrenNodes.text[1:]) -def __preprocessor_cu_contains_at_least_two_recursive_calls(node) -> bool: +def __preprocessor_cu_contains_at_least_two_recursive_calls(node: Any) -> bool: """Check if >= 2 recursive function calls are contained in a cu's code region. Returns True, if so. Returns False, else. @@ -383,7 +383,7 @@ def __preprocessor_cu_contains_at_least_two_recursive_calls(node) -> bool: return False -def check_loop_scopes(pet: PEGraphX): +def check_loop_scopes(pet: PEGraphX) -> None: """Checks if the scope of loop CUs matches these of their children. Corrects the scope of the loop CU (expand only) if necessary :param pet: PET graph""" diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py index e6c42a9b0..f25ef84a9 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py @@ -228,7 +228,7 @@ def __count_adjacent_nodes( def __check_dependences_and_predecessors( pet: PEGraphX, out_dep_edges: List[Tuple[Any, Any, Any]], parent_task: Node, cur_cu: Node -): +) -> bool: """Checks if only dependences to self, parent omittable node or path to target task exists. Checks if node is a direct successor of an omittable node or a task node. :param pet: PET Graph @@ -266,7 +266,7 @@ def __split_suggestions( taskwait_suggestions: List[TaskParallelismInfo], task_suggestions: List[TaskParallelismInfo], omittable_suggestions: List[PatternInfo], -): +) -> None: """Split suggestions into taskwait, task and omittable suggestions. :param suggestions: list of suggestions to be split :param taskwait_suggestions: list to store taskwait suggestions diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py index 844b9dfe7..d03d5065a 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py @@ -19,6 +19,7 @@ LineID, ) from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo +from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import VarName from discopop_explorer.pattern_detectors.task_parallelism.alias_detection import ( get_alias_information as get_alias_detection_result, ) @@ -162,7 +163,9 @@ def get_dict_from_cu_inst_result_file( return res_dict -def get_alias_information(pet: PEGraphX, suggestions: List[PatternInfo], source_code_files: Dict[str, str]): +def get_alias_information( + pet: PEGraphX, suggestions: List[PatternInfo], source_code_files: Dict[str, str] +) -> Dict[TaskParallelismInfo, List[List[Tuple[str, str, LineID, LineID]]]]: """Generate and return alias information dictionary. :param pet: PET Graph :param suggestions: List[PatternInfo] @@ -554,10 +557,10 @@ def identify_dependencies_for_same_functions( break # 3. get R/W information for cf's parameters based on CUInstResult.txt called_function_name_1, call_line_1 = recursive_function_call_entry_1.split(",")[0].split(" ") - lower_line_num_1 = ts_1.pragma_line - if ":" in lower_line_num_1: - lower_line_num_1 = lower_line_num_1.split(":")[1] - lower_line_num_1 = int(lower_line_num_1) + lower_line_id_1 = ts_1.pragma_line + if ":" in lower_line_id_1: + lower_line_num_str_1 = lower_line_id_1.split(":")[1] + lower_line_num_1 = int(lower_line_num_str_1) ret_val_1 = get_function_call_parameter_rw_information( pet, call_line_1, @@ -588,10 +591,10 @@ def identify_dependencies_for_same_functions( continue # 5. get R/W Information for scf called_function_name_2, call_line_2 = recursive_function_call_entry_2.split(",")[0].split(" ") - lower_line_num_2 = ts_1.pragma_line - if ":" in lower_line_num_2: - lower_line_num_2 = lower_line_num_2.split(":")[1] - lower_line_num_2 = int(lower_line_num_2) + lower_line_id_2 = ts_1.pragma_line + if ":" in lower_line_id_2: + lower_line_num_str_2 = lower_line_id_2.split(":")[1] + lower_line_num_2 = int(lower_line_num_str_2) ret_val_2 = get_function_call_parameter_rw_information( pet, call_line_2, @@ -698,7 +701,7 @@ def get_alias_for_parameter_at_position( source_code_files: Dict[str, str], visited: List[Tuple[Node, int]], called_function_cache: Dict[Any, Any], -) -> List[Tuple[str, str, LineID, LineID]]: +) -> List[Tuple[VarName, str, LineID, LineID]]: """Returns alias information for a parameter at a specific position. :param pet: PET Graph :param function: CUNode of called function @@ -1137,7 +1140,8 @@ def get_function_call_parameter_rw_information_recursion_step( # if parameter alias entry for parent function exists: if called_function_cu.name in function_parameter_alias_dict: alias_entries = function_parameter_alias_dict[called_function_cu.name] - for var_name, alias_name in alias_entries: + for var_name_str, alias_name in alias_entries: + var_name_2: VarName = VarName(var_name_str) var_name_is_modified = False # check if alias_name occurs in any depencendy in any of called_function_cu's children, # recursively visits all children cu nodes in function body. @@ -1172,7 +1176,7 @@ def get_function_call_parameter_rw_information_recursion_step( if var_name_is_modified: # update RAW information for idx, (old_var_name, raw_info, _) in enumerate(called_function_args_raw_information): - if old_var_name == var_name: + if old_var_name == var_name_2: if not raw_info: called_function_args_raw_information[idx] = (old_var_name, True, True) # second True denotes the pessimistic nature of a potential created dependency diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py index f4bd4773b..05cf01877 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py @@ -160,7 +160,7 @@ def correct_task_suggestions_in_loop_body(pet: PEGraphX, suggestions: List[Patte # check if task suggestion inside do-all loop exists if line_contained_in_region(ts._node.start_position(), loop_cu.start_position(), loop_cu.end_position()): - def find_taskwaits(cu_node: Node, visited: List[Node]): + def find_taskwaits(cu_node: Node, visited: List[Node]) -> List[Node]: if cu_node.tp_contains_taskwait: return [cu_node] result = [] @@ -175,7 +175,7 @@ def find_taskwaits(cu_node: Node, visited: List[Node]): return result # find successive taskwaits - successive_taskwait_cus = find_taskwaits(ts._node, []) + successive_taskwait_cus = cast(List[CUNode], find_taskwaits(ts._node, [])) for stws_cu in successive_taskwait_cus: if loop_cu.do_all: # check if stws is suggested at loop increment @@ -193,7 +193,10 @@ def find_taskwaits(cu_node: Node, visited: List[Node]): for s in suggestions: if type(s) == TaskParallelismInfo: if s.type is TPIType.TASKWAIT and s._node == stws_cu: - s.pragma_line = int(loop_cu.end_position().split(":")[1]) + 1 + s.pragma_line = LineID( + str(loop_cu.file_id) + ":" + str(int(loop_cu.end_position().split(":")[1]) + 1) + ) + else: # Regular loop: task = loop body, move taskwait to the end of the loop body # protect RAW to shared with critical section around CU (general) or atomic (reduction) @@ -210,7 +213,7 @@ def find_taskwaits(cu_node: Node, visited: List[Node]): for s in suggestions: if type(s) == TaskParallelismInfo: if s.type is TPIType.TASKWAIT and s._node == stws_cu: - s.pragma_line = int(loop_cu.end_position().split(":")[1]) + s.pragma_line = loop_cu.end_position() # move pragma task line to beginning of loop body (i.e. make the entire loop body a task) # set task region lines accordingly # if ts._node is a direct child of loop_cu @@ -221,9 +224,11 @@ def find_taskwaits(cu_node: Node, visited: List[Node]): " to: ", int(loop_cu.start_position().split(":")[1]) + 1, ) - ts.pragma_line = int(loop_cu.start_position().split(":")[1]) + 1 + ts.pragma_line = LineID( + str(loop_cu.file_id) + ":" + str(int(loop_cu.start_position().split(":")[1]) + 1) + ) ts.region_start_line = str(ts.pragma_line) - ts.region_end_line = loop_cu.end_position().split(":")[1] + ts.region_end_line = loop_cu.end_position() # protect RAW-Writes to shared variables with critical section # i.e. find in-deps to shared variables and suggest critical section around CUs @@ -317,7 +322,7 @@ def find_taskwaits(cu_node: Node, visited: List[Node]): def __identify_atomic_or_critical_sections( pet: PEGraphX, ts: TaskParallelismInfo, found_cus: List[Node], selector: bool -): +) -> None: """Identifies and marks atomic or critical sections. :param pet: PET Graph :param ts: task suggestion diff --git a/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py b/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py index 494cb444e..386740d49 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py @@ -7,7 +7,7 @@ # directory for details. -from typing import List, Optional, cast +from typing import Dict, List, Optional, Tuple, cast from discopop_explorer.PEGraphX import DummyNode, PEGraphX, MWType from discopop_explorer.parser import parse_inputs @@ -15,6 +15,7 @@ from discopop_explorer.pattern_detectors.do_all_detector import run_detection as detect_do_all from discopop_explorer.pattern_detectors.reduction_detector import ReductionInfo, run_detection as detect_reduction from discopop_explorer.pattern_detectors.task_parallelism.classes import ( + Task, TaskParallelismInfo, TPIType, ) @@ -62,6 +63,8 @@ detect_mw_types, get_var_definition_line_dict, ) +from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType +from discopop_library.HostpotLoader.HotspotType import HotspotType __global_llvm_cxxfilt_path: str = "" @@ -74,7 +77,7 @@ def build_preprocessed_graph_and_run_detection( cu_inst_result_file: str, llvm_cxxfilt_path: Optional[str], discopop_build_path: Optional[str], - hotspots, + hotspots: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]]], reduction_info: List[ReductionInfo], ) -> List[PatternInfo]: """execute preprocessing of given cu xml file and construct a new cu graph. @@ -162,7 +165,9 @@ def run_detection( for fork in fs: if fork.child_tasks: - result.append(TaskParallelismInfo(fork.nodes[0], TPIType.DUMMY, ["dummy_fork"], [], [], [], [])) + result.append( + TaskParallelismInfo(fork.nodes[0], TPIType.DUMMY, ["dummy_fork"], fork.start_line, [], [], []) + ) # Preprocessing check_loop_scopes(pet) # Suggestion generation diff --git a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py index 84fdafa37..9039e83c6 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py @@ -188,7 +188,7 @@ def get_predecessor_nodes(pet: PEGraphX, root: Node, visited_nodes: List[Node]) return result, visited_nodes -def check_neighbours(first: Task, second: Task): +def check_neighbours(first: Task, second: Task) -> bool: """Checks if second task immediately follows first task :param first: predecessor task @@ -241,7 +241,7 @@ def check_neighbours(first: Task, second: Task): # pass -def create_task_tree(pet: PEGraphX, root: Node): +def create_task_tree(pet: PEGraphX, root: Node) -> None: """generates task tree data from root node :param pet: PET graph @@ -252,7 +252,7 @@ def create_task_tree(pet: PEGraphX, root: Node): create_task_tree_helper(pet, root, root_task, []) -def create_task_tree_helper(pet: PEGraphX, current: Node, root: Task, visited_func: List[Node]): +def create_task_tree_helper(pet: PEGraphX, current: Node, root: Task, visited_func: List[Node]) -> None: """generates task tree data recursively :param pet: PET graph @@ -521,7 +521,7 @@ def get_called_function_and_parameter_names_from_function_call( return cast(Optional[str], function_name), result_parameters -def set_global_llvm_cxxfilt_path(value: str): +def set_global_llvm_cxxfilt_path(value: str) -> None: """setter for __global_llvm_cxxfilt_path :param value: value to place in __global_llvm_cxxfilt_path""" global __global_llvm_cxxfilt_path @@ -566,7 +566,7 @@ def contains_reduction(pet: PEGraphX, node: Node) -> bool: return False -def detect_mw_types(pet: PEGraphX, main_node: Node): +def detect_mw_types(pet: PEGraphX, main_node: Node) -> None: """The mainNode we want to compute the Task Parallelism Pattern for it use Breadth First Search (BFS) to detect all barriers and workers. 1.) all child nodes become first worker if they are not marked as worker before diff --git a/discopop_explorer/plugins/pipeline.py b/discopop_explorer/plugins/pipeline.py index 2a1a07a18..919a3ef89 100644 --- a/discopop_explorer/plugins/pipeline.py +++ b/discopop_explorer/plugins/pipeline.py @@ -17,11 +17,11 @@ after: List[float] = [] -def run_before(pet: PEGraphX): +def run_before(pet: PEGraphX) -> PEGraphX: return pet -def run_after(pet: PEGraphX): +def run_after(pet: PEGraphX) -> PEGraphX: for node in pet.all_nodes(LoopNode): check_pipeline(pet, node) @@ -31,7 +31,7 @@ def run_after(pet: PEGraphX): return pet -def check_pipeline(pet: PEGraphX, root: Node): +def check_pipeline(pet: PEGraphX, root: Node) -> None: """Tries to optimize dependencies for pipeline detection 1. Deletes independent lines, that do not contribute to the pipeline 2. Deletes similar CU (that have same dependencies), as those can be one step in the pipeline diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index d3887b749..012b7c915 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -335,7 +335,7 @@ def is_func_arg(pet: PEGraphX, var: str, node: Node) -> bool: return False -def is_scalar_val(var) -> bool: +def is_scalar_val(var: Variable) -> bool: """Checks if variable is a scalar value :param var: variable @@ -419,7 +419,7 @@ def is_first_written_new( reverse_raw_deps: Set[Tuple[NodeID, NodeID, Dependency]], reverse_war_deps: Set[Tuple[NodeID, NodeID, Dependency]], tree: Sequence[Node], -): +) -> bool: """Checks whether a variable is first written inside the current node :param var: @@ -730,7 +730,7 @@ def classify_task_vars( type: str, in_deps: List[Tuple[NodeID, NodeID, Dependency]], out_deps: List[Tuple[NodeID, NodeID, Dependency]], - used_in_task_parallelism_detection=False, + used_in_task_parallelism_detection: bool = False, ) -> Tuple[ List[Variable], List[Variable], diff --git a/discopop_explorer/variable.py b/discopop_explorer/variable.py index 379cdb60b..fbd5de32a 100644 --- a/discopop_explorer/variable.py +++ b/discopop_explorer/variable.py @@ -7,13 +7,15 @@ # directory for details. from typing import Optional +from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import VarName + class Variable(object): operation: Optional[str] def __init__(self, type, name, defLine, accessMode="", sizeInByte=0): self.type = type - self.name: str = name + self.name: VarName = name self.defLine = defLine self.operation = None self.accessMode = accessMode diff --git a/discopop_library/CodeGenerator/CodeGenerator.py b/discopop_library/CodeGenerator/CodeGenerator.py index c4d6f9efa..5bfd952e1 100644 --- a/discopop_library/CodeGenerator/CodeGenerator.py +++ b/discopop_library/CodeGenerator/CodeGenerator.py @@ -22,8 +22,8 @@ def from_pattern_info( patterns_by_type: Dict[str, List[PatternInfo]], skip_compilation_check: bool = False, compile_check_command: Optional[str] = None, - CC="clang", - CXX="clang++", + CC: str = "clang", + CXX: str = "clang++", ) -> Dict[int, str]: """Insert the given parallel patterns into the original source code. Returns a dictionary which maps the ID of every modified file to the updated contents of the file. @@ -51,8 +51,8 @@ def from_json_strings( pattern_json_strings_by_type: Dict[str, List[str]], skip_compilation_check: bool = False, compile_check_command: Optional[str] = None, - CC="clang", - CXX="clang++", + CC: str = "clang", + CXX: str = "clang++", ) -> Dict[int, str]: """Insert the parallel patterns described by the given json strings into the original source code. Returns a dictionary which maps the ID of every modified file to the updated contents of the file. @@ -124,9 +124,9 @@ def from_json_strings_with_mapping( pattern_json_strings_with_mapping_by_type: Dict[str, List[Tuple[str, DeviceID, Optional[DeviceTypeEnum]]]], skip_compilation_check: bool = False, compile_check_command: Optional[str] = None, - CC="clang", - CXX="clang++", - host_device_id=0, + CC: str = "clang", + CXX: str = "clang++", + host_device_id: int = 0, ) -> Dict[int, str]: """Insert the parallel patterns described by the given json strings into the original source code. Returns a dictionary which maps the ID of every modified file to the updated contents of the file. diff --git a/discopop_library/CodeGenerator/classes/ContentBuffer.py b/discopop_library/CodeGenerator/classes/ContentBuffer.py index 2da03f6e3..4a8f9e05f 100644 --- a/discopop_library/CodeGenerator/classes/ContentBuffer.py +++ b/discopop_library/CodeGenerator/classes/ContentBuffer.py @@ -27,7 +27,7 @@ class ContentBuffer(object): line_type: Any compile_result_buffer: str - def __init__(self, file_id: int, source_code_path: Path, tab_width: int = 4, line_type=Line): + def __init__(self, file_id: int, source_code_path: Path, tab_width: int = 4, line_type: Any = Line) -> None: self.line_type = line_type self.file_id = file_id self.lines = [] @@ -42,7 +42,7 @@ def __init__(self, file_id: int, source_code_path: Path, tab_width: int = 4, lin self.lines.append(line_obj) self.compile_result_buffer = "" - def print_lines(self): + def print_lines(self) -> None: for line in self.lines: print(line) @@ -59,7 +59,7 @@ def get_modified_source_code(self) -> str: result += line.content return result - def append_line_before(self, parent_line_num: int, line: Line, match_indentation: bool = True): + def append_line_before(self, parent_line_num: int, line: Line, match_indentation: bool = True) -> None: """Appends line before the specified parent_line_num""" for idx, potential_parent_line in enumerate(self.lines): if potential_parent_line.line_num == parent_line_num: @@ -68,7 +68,7 @@ def append_line_before(self, parent_line_num: int, line: Line, match_indentation self.lines.insert(idx, line) return - def append_line_after(self, parent_line_num: int, line: Line, match_indentation: bool = True): + def append_line_after(self, parent_line_num: int, line: Line, match_indentation: bool = True) -> None: """Appends line after the specified parent_line_num""" for idx, potential_parent_line in enumerate(self.lines): if potential_parent_line.line_num == parent_line_num: @@ -88,8 +88,8 @@ def add_pragma( add_as_comment: bool = False, skip_compilation_check: bool = False, compile_check_command: Optional[str] = None, - CC="clang", - CXX="clang++", + CC: str = "clang", + CXX: str = "clang++", match_indentation: bool = True, ) -> bool: """insert pragma into the maintained list of source code lines. diff --git a/discopop_library/CodeGenerator/classes/Line.py b/discopop_library/CodeGenerator/classes/Line.py index e43010033..448c75a5f 100644 --- a/discopop_library/CodeGenerator/classes/Line.py +++ b/discopop_library/CodeGenerator/classes/Line.py @@ -16,7 +16,7 @@ class Line(object): belongs_to_regions: List[int] belongs_to_original_line: int - def __init__(self, parent_line_num: int, line_num=None, content=""): + def __init__(self, parent_line_num: int, line_num: Optional[int] = None, content: str = ""): self.line_num = line_num self.content = content self.owns_region = None diff --git a/discopop_library/CodeGenerator/classes/UnpackedSuggestion.py b/discopop_library/CodeGenerator/classes/UnpackedSuggestion.py index 057bafed1..9eba29847 100644 --- a/discopop_library/CodeGenerator/classes/UnpackedSuggestion.py +++ b/discopop_library/CodeGenerator/classes/UnpackedSuggestion.py @@ -34,7 +34,14 @@ class UnpackedSuggestion(object): device_type: Optional[DeviceTypeEnum] host_device_id: int - def __init__(self, type_str: str, values: Dict[str, Any], device_id=None, device_type=None, host_device_id=0): + def __init__( + self, + type_str: str, + values: Dict[str, Any], + device_id: Optional[DeviceID] = None, + device_type: Optional[DeviceTypeEnum] = None, + host_device_id: int = 0, + ): self.type = type_str self.values = values self.device_id = device_id @@ -234,16 +241,16 @@ def __get_pipeline_pragmas(self) -> List[Pragma]: def __get_simple_gpu_pragmas( self, - region_start, - region_end, - contained_loops, - map_to_vars, - map_from_vars, - map_to_from_vars, - map_alloc_vars, - map_delete_vars, - consumed_vars, - produced_vars, + region_start: Any, + region_end: Any, + contained_loops: Any, + map_to_vars: Any, + map_from_vars: Any, + map_to_from_vars: Any, + map_alloc_vars: Any, + map_delete_vars: Any, + consumed_vars: Any, + produced_vars: Any, indentation: int = 0, ignore_mapping_clauses: bool = False, ) -> List[Pragma]: @@ -309,7 +316,7 @@ def __get_simple_gpu_pragmas( pragmas.append(loop_pragma) return pragmas - def __get_update_pragmas(self, update_instructions) -> List[Pragma]: + def __get_update_pragmas(self, update_instructions: List[Tuple[str, str, UpdateType, str, str]]) -> List[Pragma]: pragmas = [] for source_cu_id, sink_cu_id, update_type, target_var, pragma_line in update_instructions: pragma = Pragma() @@ -338,7 +345,9 @@ def __get_update_pragmas(self, update_instructions) -> List[Pragma]: pragmas.append(pragma) return pragmas - def __get_data_region_dependencies(self, depend_in, depend_out) -> List[Pragma]: + def __get_data_region_dependencies( + self, depend_in: List[Tuple[str, str, str]], depend_out: List[Tuple[str, str, str]] + ) -> List[Pragma]: pragmas = [] for var_name, cu_id, pragma_line in depend_in: pragma = Pragma() @@ -362,7 +371,11 @@ def __get_data_region_dependencies(self, depend_in, depend_out) -> List[Pragma]: return pragmas - def __get_data_region_pragmas(self, entry_points, exit_points) -> List[Pragma]: + def __get_data_region_pragmas( + self, + entry_points: List[Tuple[str, str, str, EntryPointType, str, EntryPointPositioning]], + exit_points: List[Tuple[str, str, str, ExitPointType, str, ExitPointPositioning]], + ) -> List[Pragma]: pragmas = [] for ( var_name, diff --git a/discopop_library/GlobalLogger/setup.py b/discopop_library/GlobalLogger/setup.py index de054793c..90d60287a 100644 --- a/discopop_library/GlobalLogger/setup.py +++ b/discopop_library/GlobalLogger/setup.py @@ -11,7 +11,7 @@ from discopop_library.ArgumentClasses.GeneralArguments import GeneralArguments -def setup_logger(arguments: GeneralArguments): +def setup_logger(arguments: GeneralArguments) -> None: if arguments.write_log: logging.basicConfig(filename="log.txt", level=arguments.log_level) else: diff --git a/discopop_library/LineMapping/diff_modifications.py b/discopop_library/LineMapping/diff_modifications.py index f12cd51c2..3d9cf6583 100644 --- a/discopop_library/LineMapping/diff_modifications.py +++ b/discopop_library/LineMapping/diff_modifications.py @@ -13,7 +13,7 @@ from discopop_library.LineMapping.save import save_line_mapping -def apply_line_mapping_modifications_from_files(file_id: int, original_file: str, modified_file: str): +def apply_line_mapping_modifications_from_files(file_id: int, original_file: str, modified_file: str) -> None: """Calculates diff between original_file and modified_file and applied modifications from the diff to the line_mapping""" if not os.path.exists(original_file): raise FileNotFoundError(original_file) @@ -45,7 +45,7 @@ def apply_line_mapping_modifications_from_files(file_id: int, original_file: str apply_line_mapping_modifications_from_diff(file_id, diff) -def apply_line_mapping_modifications_from_diff(file_id: int, diff: str): +def apply_line_mapping_modifications_from_diff(file_id: int, diff: str) -> None: """parse diff, apply line num modifications according to c,a,d values""" # get cleaned diff cleaned_diff: List[str] = [] diff --git a/discopop_library/LineMapping/initialize.py b/discopop_library/LineMapping/initialize.py index ee18dad96..e00ffd680 100644 --- a/discopop_library/LineMapping/initialize.py +++ b/discopop_library/LineMapping/initialize.py @@ -18,7 +18,7 @@ def initialize_line_mapping( file_mapping: Dict[int, Path], discopop_path: str = ".discopop", -): +) -> None: """initializes the line mapping dictionary to track line shifts due to inserted pragmas. The Dictionary will be stored in .discopop/line_mapping.json. Line ids start with 1.""" diff --git a/discopop_library/LineMapping/save.py b/discopop_library/LineMapping/save.py index 8607d5f7d..bde72187f 100644 --- a/discopop_library/LineMapping/save.py +++ b/discopop_library/LineMapping/save.py @@ -10,7 +10,7 @@ from typing import Dict -def save_line_mapping(line_mapping_dict: Dict[str, Dict[str, int]], discopop_path: str = ""): +def save_line_mapping(line_mapping_dict: Dict[str, Dict[str, int]], discopop_path: str = "") -> None: """dumps line_mapping_dict to line_mapping.json""" # dump line mapping to json file with open(os.path.join(discopop_path, "line_mapping.json"), "w+") as f: diff --git a/discopop_library/PatchGenerator/from_json_patterns.py b/discopop_library/PatchGenerator/from_json_patterns.py index 3d1b2ab84..5748c5be9 100644 --- a/discopop_library/PatchGenerator/from_json_patterns.py +++ b/discopop_library/PatchGenerator/from_json_patterns.py @@ -25,7 +25,7 @@ def from_json_patterns( patterns_by_type: Dict[str, List[str]], file_mapping: Dict[int, Path], patch_generator_dir: str, -): +) -> None: # collect metadata max_pattern_id = 0 for suggestion_type in patterns_by_type: diff --git a/discopop_library/PatchGenerator/from_optimizer_output.py b/discopop_library/PatchGenerator/from_optimizer_output.py index 53d23db08..5ce309110 100644 --- a/discopop_library/PatchGenerator/from_optimizer_output.py +++ b/discopop_library/PatchGenerator/from_optimizer_output.py @@ -29,7 +29,7 @@ def from_optimizer_output( optimizer_output_json_str: str, arguments: PatchGeneratorArguments, patch_generator_dir: str, -): +) -> None: suggestion_strings_with_mapping: Dict[str, List[Tuple[str, DeviceID, Optional[DeviceTypeEnum]]]] = dict() if arguments.verbose: print("Loading optimizer output: ") diff --git a/discopop_library/PatchGenerator/patch_generator.py b/discopop_library/PatchGenerator/patch_generator.py index cfb222ff0..fa3492eb2 100644 --- a/discopop_library/PatchGenerator/patch_generator.py +++ b/discopop_library/PatchGenerator/patch_generator.py @@ -20,7 +20,7 @@ from discopop_library.PathManagement.PathManagement import load_file_mapping -def run(arguments: PatchGeneratorArguments): +def run(arguments: PatchGeneratorArguments) -> None: logger = logging.getLogger("PatchGenerator") if arguments.verbose: diff --git a/discopop_library/discopop_optimizer/CostModels/CostModel.py b/discopop_library/discopop_optimizer/CostModels/CostModel.py index c1e0a6bbf..395ba4300 100644 --- a/discopop_library/discopop_optimizer/CostModels/CostModel.py +++ b/discopop_library/discopop_optimizer/CostModels/CostModel.py @@ -5,6 +5,7 @@ # This software may be modified and distributed under the terms of # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. +from __future__ import annotations import random import sys from typing import List, Dict, Tuple, Optional @@ -36,9 +37,9 @@ def __init__( parallelizable_costs: Expr, sequential_costs: Expr, identifier: str = "None", - path_decisions=None, + path_decisions: Optional[List[int]] = None, symbol_value_suggestions: Optional[Dict[Symbol, Expr]] = None, - ): + ) -> None: if sequential_costs == sympy.nan: raise ValueError("NAN: ", sequential_costs) if path_decisions is None: @@ -64,7 +65,7 @@ def print(self, file=sys.stdout): print("\tSERIAL") print("\t", self.sequential_costs, file=file) - def parallelizable_plus_combine(self, other): + def parallelizable_plus_combine(self, other: CostModel) -> CostModel: """Combines both models in the following fashion: f(x,y) = ==> x.parallelizable_costs + y.parallelizable_costs @@ -220,7 +221,7 @@ def __lt__(self, other): else: return False - def __plot_weibull_distributions(self, alpha: float, beta: float): + def __plot_weibull_distributions(self, alpha: float, beta: float) -> None: """For Debug reasons. Plots the left and right side heavy weibull distributions using the given parameters.""" x = np.arange(1, 100.0) / 100.0 # normalized to [0,1] diff --git a/discopop_library/discopop_optimizer/CostModels/utilities.py b/discopop_library/discopop_optimizer/CostModels/utilities.py index e48b5b088..dfb27f5a9 100644 --- a/discopop_library/discopop_optimizer/CostModels/utilities.py +++ b/discopop_library/discopop_optimizer/CostModels/utilities.py @@ -114,7 +114,7 @@ def get_node_performance_models( do_not_allow_decisions: Optional[Set[int]] = None, get_single_random_model: bool = False, ignore_node_costs: Optional[List[int]] = None, - current_device_id=None, + current_device_id: Optional[int] = None, allow_sequential: bool = False, ) -> List[CostModel]: """Returns the performance models for the given node. @@ -392,7 +392,7 @@ def get_performance_models_for_children( return child_models -def print_introduced_symbols_per_node(graph: nx.DiGraph): +def print_introduced_symbols_per_node(graph: nx.DiGraph) -> None: print("Introduced Symbols:") for node_id in graph.nodes: print("NodeID: ", node_id) diff --git a/discopop_library/discopop_optimizer/DataTransfers/DataTransfers.py b/discopop_library/discopop_optimizer/DataTransfers/DataTransfers.py index d1fe46299..4a942aba8 100644 --- a/discopop_library/discopop_optimizer/DataTransfers/DataTransfers.py +++ b/discopop_library/discopop_optimizer/DataTransfers/DataTransfers.py @@ -11,6 +11,7 @@ from discopop_explorer.PEGraphX import EdgeType, MemoryRegion from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel +from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.context.ContextObject import ContextObject from discopop_library.discopop_optimizer.classes.nodes.ContextNode import ContextNode from discopop_library.discopop_optimizer.classes.nodes.DeviceSwitch import DeviceSwitch @@ -30,7 +31,7 @@ def calculate_data_transfers( - graph: nx.DiGraph, function_performance_models: Dict[FunctionRoot, List[CostModel]], experiment + graph: nx.DiGraph, function_performance_models: Dict[FunctionRoot, List[CostModel]], experiment: Experiment ) -> Dict[FunctionRoot, List[Tuple[CostModel, ContextObject]]]: """Calculate data transfers for each performance model and append the respective ContextObject to the result.""" result_dict: Dict[FunctionRoot, List[Tuple[CostModel, ContextObject]]] = dict() @@ -51,7 +52,7 @@ def get_path_context_iterative( graph: nx.DiGraph, model: CostModel, context: ContextObject, - experiment, + experiment: Experiment, top_level_call: bool = False, ) -> ContextObject: """passes the context Object along the path and returns the context once the end has been reached""" @@ -161,6 +162,8 @@ def get_path_context_iterative( if target in cu_nodes_in_function: continue # target outside the function. MemoryRegions qualifies for synchronization at the end of the function + if out_dep_edge[2].memory_region is None: + raise ValueError("Value is None!") filter.add(out_dep_edge[2].memory_region) # collect all write data accesses which might need synchronization @@ -193,7 +196,7 @@ def get_path_context_iterative( def get_path_context( - node_id: int, graph: nx.DiGraph, model: CostModel, context: ContextObject, experiment + node_id: int, graph: nx.DiGraph, model: CostModel, context: ContextObject, experiment: Experiment ) -> ContextObject: """passes the context Object along the path and returns the context once the end has been reached""" # push device id to stack if necessary @@ -271,7 +274,7 @@ def get_path_context( def __check_current_node( - node_id: int, graph: nx.DiGraph, model: CostModel, context: ContextObject, experiment + node_id: int, graph: nx.DiGraph, model: CostModel, context: ContextObject, experiment: Experiment ) -> ContextObject: """Check if the given node results in modifications to the given context. Return a modified version of the context which contains the required updates.""" @@ -344,7 +347,7 @@ def __check_current_node( def __check_children( - node_id: int, graph: nx.DiGraph, model: CostModel, context: ContextObject, experiment + node_id: int, graph: nx.DiGraph, model: CostModel, context: ContextObject, experiment: Experiment ) -> ContextObject: # pass context to all children for child in get_children(graph, node_id): diff --git a/discopop_library/discopop_optimizer/DataTransfers/NewDataTransfers.py b/discopop_library/discopop_optimizer/DataTransfers/NewDataTransfers.py index de1366327..8f1149ae5 100644 --- a/discopop_library/discopop_optimizer/DataTransfers/NewDataTransfers.py +++ b/discopop_library/discopop_optimizer/DataTransfers/NewDataTransfers.py @@ -178,7 +178,7 @@ def perform_read(self, node_id: int, device_id: DeviceID, rda: ReadDataAccess) - return updates - def perform_write(self, node_id: int, device_id: DeviceID, wda: WriteDataAccess): + def perform_write(self, node_id: int, device_id: DeviceID, wda: WriteDataAccess) -> None: if device_id not in self.memory: self.memory[device_id] = dict() self.memory[device_id][wda.memory_region] = wda @@ -198,7 +198,7 @@ class DataFrame(object): def __init__(self): self.entered_data_regions_by_device = dict() - def parse_update(self, update: Update): + def parse_update(self, update: Update) -> None: if update.is_first_data_occurrence: if update.target_device_id not in self.entered_data_regions_by_device: self.entered_data_regions_by_device[update.target_device_id] = [] @@ -317,7 +317,7 @@ def log_state(self): def new_calculate_data_transfers( graph: nx.DiGraph, decisions: List[int], - experiment, + experiment: Experiment, targeted_functions: Optional[List[int]] = None, arguments: Optional[OptimizerArguments] = None, ) -> List[Update]: @@ -491,7 +491,7 @@ def new_calculate_data_transfers( def calculate_data_transfers_by_models( - graph: nx.DiGraph, function_performance_models: Dict[FunctionRoot, List[CostModel]], experiment + graph: nx.DiGraph, function_performance_models: Dict[FunctionRoot, List[CostModel]], experiment: Experiment ) -> Dict[FunctionRoot, List[Tuple[CostModel, ContextObject]]]: """Calculate data transfers for each performance model and append the respective ContextObject to the result.""" result_dict: Dict[FunctionRoot, List[Tuple[CostModel, ContextObject]]] = dict() diff --git a/discopop_library/discopop_optimizer/DataTransfers/calculate_configuration_data_movement.py b/discopop_library/discopop_optimizer/DataTransfers/calculate_configuration_data_movement.py index 84052a8c5..847a4279c 100644 --- a/discopop_library/discopop_optimizer/DataTransfers/calculate_configuration_data_movement.py +++ b/discopop_library/discopop_optimizer/DataTransfers/calculate_configuration_data_movement.py @@ -16,7 +16,7 @@ from discopop_library.result_classes.OptimizerOutputPattern import OptimizerOutputPattern -def calculate_data_movement(experiment: Experiment): +def calculate_data_movement(experiment: Experiment) -> None: """Calculate the necessary data movement for each suggestion created by the optimizer""" for idx, suggestion in enumerate(experiment.detection_result.patterns.optimizer_output): diff --git a/discopop_library/discopop_optimizer/Microbench/DelaunayInterpolatedMicrobench.py b/discopop_library/discopop_optimizer/Microbench/DelaunayInterpolatedMicrobench.py index ecea207d8..a590fdcfd 100644 --- a/discopop_library/discopop_optimizer/Microbench/DelaunayInterpolatedMicrobench.py +++ b/discopop_library/discopop_optimizer/Microbench/DelaunayInterpolatedMicrobench.py @@ -44,27 +44,29 @@ def __init__( if removeOutliers: self.data.removeOutliers() - def removeZeroParameters(self): + def removeZeroParameters(self) -> None: self.data.removeZeroParameters() self.__isInterpolated = False - def clampValues(self, min: float = 0.0, max: float = float("inf")): + def clampValues(self, min: float = 0.0, max: float = float("inf")) -> None: self.data.clampValues() self.__isInterpolated = False - def removeOutliers(self): + def removeOutliers(self) -> None: self.data.removeOutliers() self.__isInterpolated = False - def useMedian(self): + def useMedian(self) -> None: self.data.useMedian() self.__isInterpolated = False - def useMean(self): + def useMean(self) -> None: self.data.useMean() self.__isInterpolated = False - def __getTuples(self, benchType: MicrobenchType, benchDim: MicrobenchDimension): + def __getTuples( + self, benchType: MicrobenchType, benchDim: MicrobenchDimension + ) -> List[Tuple[int, Union[int, float], int, float]]: tuples: List[Tuple[int, Union[int, float], int, float]] = [] for benchCoord, values in self.data[benchType][benchDim].items(): tuples.append((*benchCoord, np.median(values).item())) @@ -95,8 +97,8 @@ def evaluateInterpolation( benchType: MicrobenchType, benchDim: MicrobenchDimension, benchCoord: Union[MicrobenchCoordinate, Tuple[int, float, float]], - ): + ) -> float: if not self.__isInterpolated: self.__interpolate() self.__isInterpolated = True - return self.interpolator[benchType][benchDim](benchCoord) / 1000000.0 # convert microseconds to seconds + return float(self.interpolator[benchType][benchDim](benchCoord) / 1000000.0) # convert microseconds to seconds diff --git a/discopop_library/discopop_optimizer/Microbench/ExtrapInterpolatedMicrobench.py b/discopop_library/discopop_optimizer/Microbench/ExtrapInterpolatedMicrobench.py index 960549456..6a190f2c7 100644 --- a/discopop_library/discopop_optimizer/Microbench/ExtrapInterpolatedMicrobench.py +++ b/discopop_library/discopop_optimizer/Microbench/ExtrapInterpolatedMicrobench.py @@ -5,7 +5,8 @@ # This software may be modified and distributed under the terms of # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. -from typing import Dict, Tuple, Union +from typing import Dict, Tuple, Union, cast + import sympy from extrap.entities.callpath import Callpath # type: ignore @@ -55,14 +56,14 @@ def getFunctionString( self, benchType: MicrobenchType = MicrobenchType.DOALL, benchDim: MicrobenchDimension = MicrobenchDimension.OVERHEAD, - ): - return self.models[(Callpath(benchType), Metric(benchDim))].hypothesis.function.to_string() + ) -> str: + return str(self.models[(Callpath(benchType), Metric(benchDim))].hypothesis.function.to_string()) def getFunctionSympy( self, benchType: MicrobenchType = MicrobenchType.DOALL, benchDim: MicrobenchDimension = MicrobenchDimension.OVERHEAD, - ): + ) -> sympy.Expr: function_str = self.getFunctionString(benchType, benchDim) # NOTE: replacement order matters! "ab".replace("a","b").replace("b","a") --> "aa", NOT "ba" function_str = function_str.replace("^", "**") @@ -72,7 +73,7 @@ def getFunctionSympy( # define replacements to match representations used in extrap output function_mappings = {"log2": lambda x: sympy.log(x, 2)} expr = parse_expr(function_str, local_dict=function_mappings) - return expr + return cast(sympy.Expr, expr) def getMeasurements(self): raise NotImplementedError("TODO") # TODO @@ -85,5 +86,7 @@ def evaluateInterpolation( benchType: MicrobenchType, benchDim: MicrobenchDimension, benchCoord: Union[MicrobenchCoordinate, Tuple[int, float, float]], - ): - return self.models[(Callpath(benchType), Metric(benchDim))].hypothesis.function.evaluate([*benchCoord]) + ) -> float: + return cast( + float, self.models[(Callpath(benchType), Metric(benchDim))].hypothesis.function.evaluate([*benchCoord]) + ) diff --git a/discopop_library/discopop_optimizer/Microbench/Microbench.py b/discopop_library/discopop_optimizer/Microbench/Microbench.py index b25360e9b..429493621 100644 --- a/discopop_library/discopop_optimizer/Microbench/Microbench.py +++ b/discopop_library/discopop_optimizer/Microbench/Microbench.py @@ -73,10 +73,10 @@ def plotInterpolation( type: MicrobenchType, dim: MicrobenchDimension, iterations: int, - threads=range(1, 9), - workloads=range(0, 201), + threads: range = range(1, 9), + workloads: range = range(0, 201), file: Optional[Path] = None, - ): + ) -> None: logging.info("plotting interpolation to %s", str(file.absolute() if file else "")) # coords = list(self.getMeasurements()[type][dim].keys()) # minWorkload = coords[0].workload diff --git a/discopop_library/discopop_optimizer/Microbench/PureDataMicrobench.py b/discopop_library/discopop_optimizer/Microbench/PureDataMicrobench.py index 545e49f78..0aa9f675f 100644 --- a/discopop_library/discopop_optimizer/Microbench/PureDataMicrobench.py +++ b/discopop_library/discopop_optimizer/Microbench/PureDataMicrobench.py @@ -9,7 +9,7 @@ import json from dataclasses import dataclass -from typing import Dict, List, Tuple, TypeVar, Union, overload +from typing import Callable, Dict, List, Tuple, TypeVar, Union, overload import numpy as np @@ -23,7 +23,7 @@ T = TypeVar("T") -def __partition(pred, list: List[T]) -> Tuple[List[T], List[T]]: +def __partition(pred: Callable[[T], bool], list: List[T]) -> Tuple[List[T], List[T]]: trues: List[T] = [] falses: List[T] = [] for item in list: @@ -34,7 +34,7 @@ def __partition(pred, list: List[T]) -> Tuple[List[T], List[T]]: return trues, falses -def __remove_outliers_using_iqr(values: List[float], iqr_factor=1.5) -> List[float]: +def __remove_outliers_using_iqr(values: List[float], iqr_factor: float = 1.5) -> List[float]: values.sort() q1, q3 = np.percentile(values, [25, 75], method="linear") iqr = q3 - q1 @@ -153,7 +153,7 @@ def clampValues( ], min: float = float("-inf"), max: float = float("inf"), - ): + ) -> None: for type, dimMap in self.measurements.items(): for d in dim: if d in dimMap: @@ -162,7 +162,7 @@ def clampValues( v if v >= min and v <= max else (min if v < min else max) for v in values ] - def merge(self, other: PureDataMicrobench): + def merge(self, other: PureDataMicrobench) -> None: for type, dimMap in other.measurements.items(): if type not in self.measurements: self.measurements[type] = {} @@ -175,7 +175,7 @@ def merge(self, other: PureDataMicrobench): self.measurements[type][dim][coord].extend(values) # TODO check for duplicates? (but maybe we want them?) - def mergeAll(self, others: List[PureDataMicrobench]): + def mergeAll(self, others: List[PureDataMicrobench]) -> None: for other in others: self.merge(other) @@ -214,5 +214,5 @@ def evaluateInterpolation( benchType: MicrobenchType, benchDim: MicrobenchDimension, benchCoord: Union[MicrobenchCoordinate, Tuple[int, float, float]], - ): + ) -> float: raise TypeError("This class does not support interpolation.") diff --git a/discopop_library/discopop_optimizer/PETParser/PETParser.py b/discopop_library/discopop_optimizer/PETParser/PETParser.py index d88abbfd2..b7540bb9a 100644 --- a/discopop_library/discopop_optimizer/PETParser/PETParser.py +++ b/discopop_library/discopop_optimizer/PETParser/PETParser.py @@ -495,7 +495,7 @@ def __flatten_function_graphs(self): print("\tTimeout after: ", timeout, "s") self.invalid_functions.add(function) - def __fix_too_many_successors(self, node, dbg_function_node=None) -> bool: + def __fix_too_many_successors(self, node: int, dbg_function_node: Optional[FunctionRoot] = None) -> bool: """Return True if a graph modification has been applied. False otherwise.""" retval = False @@ -580,7 +580,7 @@ def __fix_too_many_successors(self, node, dbg_function_node=None) -> bool: retval = True return retval - def __fix_too_many_predecessors(self, node) -> Tuple[bool, List[int]]: + def __fix_too_many_predecessors(self, node: int) -> Tuple[bool, List[int]]: """Return True if a graph modification has been applied. False otherwise.""" retval = False modified_nodes: List[int] = [] @@ -857,7 +857,7 @@ def __fix_empty_branches( added_node_ids.append(dummy_node_id) return added_node_ids - def __insert_context_nodes(self, node_list: List[int]): + def __insert_context_nodes(self, node_list: List[int]) -> None: """flattens the graph via inserting context nodes""" modification_found = True from time import time diff --git a/discopop_library/discopop_optimizer/UpdateOptimization/RemoveDuplicatedUpdates.py b/discopop_library/discopop_optimizer/UpdateOptimization/RemoveDuplicatedUpdates.py index 94f4a003a..f5434e5d0 100644 --- a/discopop_library/discopop_optimizer/UpdateOptimization/RemoveDuplicatedUpdates.py +++ b/discopop_library/discopop_optimizer/UpdateOptimization/RemoveDuplicatedUpdates.py @@ -13,7 +13,9 @@ from discopop_library.result_classes.OptimizerOutputPattern import OptimizerOutputPattern -def remove_duplicated_updates(configuration: OptimizerOutputPattern, arguments: OptimizerArguments): +def remove_duplicated_updates( + configuration: OptimizerOutputPattern, arguments: OptimizerArguments +) -> OptimizerOutputPattern: logger = logging.getLogger("Optimizer").getChild("RemoveDuplicatedUpdates") logger.setLevel(arguments.log_level) cleaned_updates: List[Update] = [] diff --git a/discopop_library/discopop_optimizer/Variables/Experiment.py b/discopop_library/discopop_optimizer/Variables/Experiment.py index 56db58eea..cefdb33c3 100644 --- a/discopop_library/discopop_optimizer/Variables/Experiment.py +++ b/discopop_library/discopop_optimizer/Variables/Experiment.py @@ -14,17 +14,18 @@ from sympy import Integer, Symbol, Expr, Float # type: ignore from discopop_explorer.PEGraphX import MemoryRegion -from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType from discopop_library.HostpotLoader.HotspotType import HotspotType from discopop_library.MemoryRegions.utils import get_sizes_of_memory_regions from discopop_library.PathManagement.PathManagement import load_file_mapping -from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel from discopop_library.discopop_optimizer.OptimizerArguments import OptimizerArguments -from discopop_library.discopop_optimizer.classes.context.ContextObject import ContextObject from discopop_library.discopop_optimizer.classes.enums.Distributions import FreeSymbolDistribution + +from discopop_library.discopop_optimizer.classes.context.ContextObject import ContextObject +from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType +from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel from discopop_library.discopop_optimizer.classes.nodes.FunctionRoot import FunctionRoot -from discopop_library.discopop_optimizer.classes.system.System import System from discopop_library.result_classes.DetectionResult import DetectionResult +from discopop_library.discopop_optimizer.classes.system.System import System class Experiment(object): @@ -131,7 +132,7 @@ def get_memory_region_size( else: return Integer(self.__memory_region_sizes[memory_region]), Integer(0) - def register_free_symbol(self, symbol: Symbol, value_suggestion: Optional[Expr] = None): + def register_free_symbol(self, symbol: Symbol, value_suggestion: Optional[Expr] = None) -> None: self.free_symbols.add(symbol) if value_suggestion is not None: self.suggested_values[symbol] = value_suggestion diff --git a/discopop_library/discopop_optimizer/Variables/ExperimentUtils.py b/discopop_library/discopop_optimizer/Variables/ExperimentUtils.py index 707dc62d0..4e144c728 100644 --- a/discopop_library/discopop_optimizer/Variables/ExperimentUtils.py +++ b/discopop_library/discopop_optimizer/Variables/ExperimentUtils.py @@ -44,7 +44,7 @@ def show_function_models( parent_frame: tk.Frame, destroy_window_after_execution: bool, show_functions: Optional[List[FunctionRoot]] = None, -): +) -> None: considered_functions = show_functions if show_functions is not None else experiment.function_models # show function selection dialogue parent_frame.rowconfigure(0, weight=1) @@ -104,7 +104,7 @@ def __on_press(): def perform_headless_execution( experiment: Experiment, -): +) -> None: print("Headless execution...") for function in experiment.function_models: print("\t", function.name) @@ -128,7 +128,7 @@ def perform_headless_execution( experiment.function_models[function] = updated_options -def export_to_json(experiment: Experiment, export_path): +def export_to_json(experiment: Experiment, export_path: str) -> None: # convert functionRoot in function_models to node ids to_be_added = [] to_be_deleted = [] @@ -148,7 +148,7 @@ def export_to_json(experiment: Experiment, export_path): pickle.dump(experiment, open(experiment_dump_path, "wb")) -def export_patterns_to_json(experiment: Experiment, export_path): +def export_patterns_to_json(experiment: Experiment, export_path: str) -> None: detection_result_copy = copy.deepcopy(experiment.detection_result) # pet is not serializable and needs to be deleted del detection_result_copy.pet @@ -156,7 +156,7 @@ def export_patterns_to_json(experiment: Experiment, export_path): json.dump(detection_result_copy, f, indent=2, cls=PatternBaseSerializer) -def export_detection_result_to_json(experiment: Experiment, export_path): +def export_detection_result_to_json(experiment: Experiment, export_path: str) -> None: with open(export_path, "w+") as f: f.write(experiment.detection_result.dump_to_pickled_json()) f.flush() @@ -182,7 +182,7 @@ def restore_session(json_file: str) -> Experiment: return experiment -def create_optimization_graph(experiment: Experiment, arguments: OptimizerArguments): +def create_optimization_graph(experiment: Experiment, arguments: OptimizerArguments) -> None: if arguments.verbose: print("Creating optimization graph...", end="") pet_parser = PETParser(experiment) @@ -209,7 +209,7 @@ def get_sequential_cost_model(experiment: Experiment) -> Dict[FunctionRoot, List def initialize_free_symbol_ranges_and_distributions( experiment: Experiment, arguments: OptimizerArguments, system: System -): +) -> None: free_symbol_ranges: Dict[Symbol, Tuple[float, float]] = dict() free_symbol_distributions: Dict[Symbol, FreeSymbolDistribution] = dict() sorted_free_symbols = sorted(list(experiment.free_symbols), key=lambda x: x.name) diff --git a/discopop_library/discopop_optimizer/classes/context/ContextObject.py b/discopop_library/discopop_optimizer/classes/context/ContextObject.py index af339ed95..02804ab30 100644 --- a/discopop_library/discopop_optimizer/classes/context/ContextObject.py +++ b/discopop_library/discopop_optimizer/classes/context/ContextObject.py @@ -5,13 +5,19 @@ # This software may be modified and distributed under the terms of # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. +from __future__ import annotations from typing import Dict, Set, List, Optional import warnings + from sympy import Expr, Integer, Symbol # type: ignore import networkx as nx # type: ignore from discopop_explorer.PEGraphX import MemoryRegion +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.context.Update import Update from discopop_library.discopop_optimizer.classes.types.Aliases import DeviceID from discopop_library.discopop_optimizer.classes.types.DataAccessType import ( @@ -46,9 +52,9 @@ def calculate_and_perform_necessary_updates( reading_device_id: int, reading_node_id: int, graph: nx.DiGraph, - experiment, + experiment: Experiment, updates_originated_from: Optional[int] = None, - ): + ) -> ContextObject: """checks if the specified list of ReadDataAccesses performed by the specified device id makes updates necessary. If so, the updates will get append to the list of updates of the current ContextObject. The list of seen writes by device of the ContextObject will be updated to reflect the identified data transfers. @@ -180,6 +186,8 @@ def calculate_and_perform_necessary_updates( self.initialize_seen_writes_by_device( update.target_device_id, update.write_data_access.memory_region ) + if update.target_device_id is None: + raise ValueError("Value is None") self.__add_seen_write( update.target_device_id, update.write_data_access.memory_region, update.write_data_access ) @@ -188,7 +196,7 @@ def calculate_and_perform_necessary_updates( return self - def add_writes(self, node_writes: Set[WriteDataAccess], writing_device_id: int): + def add_writes(self, node_writes: Set[WriteDataAccess], writing_device_id: int) -> ContextObject: """Add the specified writes to the list of seen writes of the given device and returns a reference to this ContextObject.""" # check if the device is known to the context @@ -203,7 +211,7 @@ def add_writes(self, node_writes: Set[WriteDataAccess], writing_device_id: int): self.__add_seen_write(writing_device_id, write.memory_region, write) return self - def set_last_visited_node_id(self, node_id: int): + def set_last_visited_node_id(self, node_id: int) -> None: self.last_visited_node_id = node_id def get_seen_writes_by_device(self, device_id: DeviceID) -> Dict[MemoryRegion, Set[WriteDataAccess]]: @@ -226,19 +234,19 @@ def get_seen_writes_by_device(self, device_id: DeviceID) -> Dict[MemoryRegion, S return seen_dict - def initialize_seen_writes_by_device(self, device_id: DeviceID, memory_region: MemoryRegion): + def initialize_seen_writes_by_device(self, device_id: DeviceID, memory_region: MemoryRegion) -> None: if device_id not in self.seen_writes_by_device: self.seen_writes_by_device[device_id] = dict() self.seen_writes_by_device[device_id][memory_region] = set() - def __add_seen_write(self, device_id, memory_region: MemoryRegion, write: WriteDataAccess): + def __add_seen_write(self, device_id: int, memory_region: MemoryRegion, write: WriteDataAccess) -> None: if device_id not in self.seen_writes_by_device: self.seen_writes_by_device[device_id] = dict() if memory_region not in self.seen_writes_by_device[device_id]: self.seen_writes_by_device[device_id][memory_region] = set() self.seen_writes_by_device[device_id][memory_region].add(write) - def __get_known_device_ids(self): + def __get_known_device_ids(self) -> Set[DeviceID]: seen_devices: Set[DeviceID] = set() for stack_entry in self.snapshot_stack: for device_id in stack_entry[0]: diff --git a/discopop_library/discopop_optimizer/classes/nodes/ContextMerge.py b/discopop_library/discopop_optimizer/classes/nodes/ContextMerge.py index c63985d24..5ce59dc1a 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/ContextMerge.py +++ b/discopop_library/discopop_optimizer/classes/nodes/ContextMerge.py @@ -11,12 +11,13 @@ import networkx as nx # type: ignore from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel +from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.context.ContextObject import ContextObject from discopop_library.discopop_optimizer.classes.nodes.ContextNode import ContextNode class ContextMerge(ContextNode): - def __init__(self, node_id: int, experiment): + def __init__(self, node_id: int, experiment: Experiment): super().__init__(node_id, experiment) def get_plot_label(self) -> str: diff --git a/discopop_library/discopop_optimizer/classes/nodes/ContextNode.py b/discopop_library/discopop_optimizer/classes/nodes/ContextNode.py index 4f8679e4f..42ff71378 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/ContextNode.py +++ b/discopop_library/discopop_optimizer/classes/nodes/ContextNode.py @@ -9,12 +9,13 @@ from sympy import Integer from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel +from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.context.ContextObject import ContextObject from discopop_library.discopop_optimizer.classes.nodes.Workload import Workload class ContextNode(Workload): - def __init__(self, node_id: int, experiment): + def __init__(self, node_id: int, experiment: Experiment): super().__init__( node_id, experiment, diff --git a/discopop_library/discopop_optimizer/classes/nodes/ContextRestore.py b/discopop_library/discopop_optimizer/classes/nodes/ContextRestore.py index fe35f2798..219f74184 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/ContextRestore.py +++ b/discopop_library/discopop_optimizer/classes/nodes/ContextRestore.py @@ -11,12 +11,13 @@ import networkx as nx # type: ignore from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel +from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.context.ContextObject import ContextObject from discopop_library.discopop_optimizer.classes.nodes.ContextNode import ContextNode class ContextRestore(ContextNode): - def __init__(self, node_id: int, experiment): + def __init__(self, node_id: int, experiment: Experiment): super().__init__(node_id, experiment) def get_plot_label(self) -> str: diff --git a/discopop_library/discopop_optimizer/classes/nodes/ContextSave.py b/discopop_library/discopop_optimizer/classes/nodes/ContextSave.py index 35fe85d1c..5c3c742bd 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/ContextSave.py +++ b/discopop_library/discopop_optimizer/classes/nodes/ContextSave.py @@ -11,13 +11,14 @@ import networkx as nx # type: ignore from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel +from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.context.ContextObject import ContextObject from discopop_library.discopop_optimizer.classes.nodes.ContextNode import ContextNode from discopop_library.discopop_optimizer.utilities.MOGUtilities import show class ContextSave(ContextNode): - def __init__(self, node_id: int, experiment): + def __init__(self, node_id: int, experiment: Experiment): super().__init__(node_id, experiment) def get_plot_label(self) -> str: diff --git a/discopop_library/discopop_optimizer/classes/nodes/ContextSnapshot.py b/discopop_library/discopop_optimizer/classes/nodes/ContextSnapshot.py index 3f2a83457..343f4e34f 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/ContextSnapshot.py +++ b/discopop_library/discopop_optimizer/classes/nodes/ContextSnapshot.py @@ -10,12 +10,13 @@ import networkx as nx # type: ignore from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel +from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.context.ContextObject import ContextObject from discopop_library.discopop_optimizer.classes.nodes.ContextNode import ContextNode class ContextSnapshot(ContextNode): - def __init__(self, node_id: int, experiment): + def __init__(self, node_id: int, experiment: Experiment): super().__init__(node_id, experiment) def get_plot_label(self) -> str: diff --git a/discopop_library/discopop_optimizer/classes/nodes/ContextSnapshotPop.py b/discopop_library/discopop_optimizer/classes/nodes/ContextSnapshotPop.py index 233845707..5f244d4dd 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/ContextSnapshotPop.py +++ b/discopop_library/discopop_optimizer/classes/nodes/ContextSnapshotPop.py @@ -9,12 +9,13 @@ import networkx as nx # type: ignore from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel +from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.context.ContextObject import ContextObject from discopop_library.discopop_optimizer.classes.nodes.ContextNode import ContextNode class ContextSnapshotPop(ContextNode): - def __init__(self, node_id: int, experiment): + def __init__(self, node_id: int, experiment: Experiment): super().__init__(node_id, experiment) def get_plot_label(self) -> str: diff --git a/discopop_library/discopop_optimizer/classes/nodes/DeviceSwitch.py b/discopop_library/discopop_optimizer/classes/nodes/DeviceSwitch.py index 549551eda..90d7a5016 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/DeviceSwitch.py +++ b/discopop_library/discopop_optimizer/classes/nodes/DeviceSwitch.py @@ -8,6 +8,7 @@ from typing import Optional, Set from sympy import Function, Symbol, Integer, Expr +from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.types.DataAccessType import WriteDataAccess # type: ignore from discopop_explorer.PEGraphX import NodeID @@ -20,7 +21,7 @@ class DeviceSwitch(Workload): def __init__( self, node_id: int, - experiment, + experiment: Experiment, cu_id: Optional[NodeID], sequential_workload: Optional[Expr], parallelizable_workload: Optional[Expr], diff --git a/discopop_library/discopop_optimizer/classes/nodes/FunctionReturn.py b/discopop_library/discopop_optimizer/classes/nodes/FunctionReturn.py index 164fb81c0..a7358773a 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/FunctionReturn.py +++ b/discopop_library/discopop_optimizer/classes/nodes/FunctionReturn.py @@ -7,11 +7,12 @@ # directory for details. import networkx as nx # type: ignore +from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.nodes.ContextNode import ContextNode class FunctionReturn(ContextNode): - def __init__(self, node_id: int, experiment): + def __init__(self, node_id: int, experiment: Experiment): super().__init__(node_id, experiment) def get_plot_label(self) -> str: diff --git a/discopop_library/discopop_optimizer/classes/nodes/FunctionRoot.py b/discopop_library/discopop_optimizer/classes/nodes/FunctionRoot.py index 9ebdea509..25963102f 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/FunctionRoot.py +++ b/discopop_library/discopop_optimizer/classes/nodes/FunctionRoot.py @@ -5,13 +5,19 @@ # This software may be modified and distributed under the terms of # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. -from typing import Optional +from __future__ import annotations +from typing import Any, List, Optional from sympy import Function, Symbol, Integer, Expr # type: ignore from discopop_explorer.PEGraphX import NodeID from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.nodes.Workload import Workload +from discopop_library.discopop_optimizer.classes.system.devices.Device import Device class FunctionRoot(Workload): @@ -20,7 +26,7 @@ class FunctionRoot(Workload): sequential_costs: Expr performance_model: CostModel - def __init__(self, node_id: int, experiment, cu_id: Optional[NodeID], name: str): + def __init__(self, node_id: int, experiment: Experiment, cu_id: Optional[NodeID], name: str): super().__init__( node_id, experiment, @@ -42,7 +48,9 @@ def __init__(self, node_id: int, experiment, cu_id: Optional[NodeID], name: str) def get_plot_label(self) -> str: return self.name - def get_cost_model(self, experiment, all_function_nodes, current_device) -> CostModel: + def get_cost_model( + self, experiment: Experiment, all_function_nodes: List[Any], current_device: Device + ) -> CostModel: """Model: Spawn overhead + children""" # todo this is only a dummy, not a finished model! diff --git a/discopop_library/discopop_optimizer/classes/nodes/GenericNode.py b/discopop_library/discopop_optimizer/classes/nodes/GenericNode.py index fba64254a..0f77acbdf 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/GenericNode.py +++ b/discopop_library/discopop_optimizer/classes/nodes/GenericNode.py @@ -5,12 +5,21 @@ # This software may be modified and distributed under the terms of # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. +from __future__ import annotations from typing import Optional, List, Set from sympy import Symbol, Function, Integer # type: ignore from discopop_explorer.PEGraphX import NodeID +from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + print("TYPE CHECKING") + from discopop_library.discopop_optimizer.classes.nodes.FunctionRoot import FunctionRoot + from discopop_library.discopop_optimizer.Variables.Experiment import Experiment +from discopop_library.discopop_optimizer.classes.system.devices.Device import Device from discopop_library.discopop_optimizer.classes.types.Aliases import DeviceID from discopop_library.discopop_optimizer.classes.types.DataAccessType import ( ReadDataAccess, @@ -28,13 +37,12 @@ class GenericNode(object): read_memory_regions: Set[ReadDataAccess] device_id: DeviceID execute_in_parallel: bool - branch_affiliation: List[int] def __init__( self, node_id: int, - experiment, + experiment: Experiment, cu_id: Optional[NodeID] = None, written_memory_regions: Optional[Set[WriteDataAccess]] = None, read_memory_regions: Optional[Set[ReadDataAccess]] = None, @@ -45,7 +53,7 @@ def __init__( self.original_cu_id = cu_id # used for the creation of update suggestions self.introduced_symbols = [] self.performance_model = CostModel(Integer(0), Integer(0)) - self.suggestion = None + self.suggestion: Optional[PatternInfo] = None self.suggestion_type: Optional[str] = None self.branch_affiliation = [] self.execute_in_parallel = False @@ -74,10 +82,14 @@ def get_plot_label(self) -> str: def get_hover_text(self) -> str: return "" - def get_cost_model(self, experiment, all_function_nodes, current_device) -> CostModel: + def get_cost_model( + self, experiment: Experiment, all_function_nodes: List[FunctionRoot], current_device: Device + ) -> CostModel: raise NotImplementedError("Implementation needs to be provided by derived class: !", type(self)) - def register_child(self, other, experiment, all_function_nodes, current_device): + def register_child( + self, other: CostModel, experiment: Experiment, all_function_nodes: List[FunctionRoot], current_device: Device + ) -> CostModel: """Registers a child node for the given model. Does not modify the stored model in self or other.""" raise NotImplementedError("Implementation needs to be provided by derived class: !", type(self)) diff --git a/discopop_library/discopop_optimizer/classes/nodes/Loop.py b/discopop_library/discopop_optimizer/classes/nodes/Loop.py index b3f3cf9a3..783c80167 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/Loop.py +++ b/discopop_library/discopop_optimizer/classes/nodes/Loop.py @@ -5,14 +5,16 @@ # This software may be modified and distributed under the terms of # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. -from typing import Optional +from typing import List, Optional from sympy import Symbol, Integer, Expr, Float # type: ignore from discopop_explorer.PEGraphX import NodeID from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel from discopop_library.discopop_optimizer.Variables.Experiment import Experiment +from discopop_library.discopop_optimizer.classes.nodes.FunctionRoot import FunctionRoot from discopop_library.discopop_optimizer.classes.nodes.Workload import Workload +from discopop_library.discopop_optimizer.classes.system.devices.Device import Device class Loop(Workload): @@ -89,7 +91,9 @@ def get_hover_text(self) -> str: "Device ID: " + str(self.device_id) ) - def get_cost_model(self, experiment, all_function_nodes, current_device) -> CostModel: + def get_cost_model( + self, experiment: Experiment, all_function_nodes: List[FunctionRoot], current_device: Device + ) -> CostModel: """Performance model of a workload consists of the workload itself. Individual Workloads are assumed to be not parallelizable. Workloads of Loop etc. are parallelizable.""" @@ -111,7 +115,9 @@ def get_cost_model(self, experiment, all_function_nodes, current_device) -> Cost return cm - def register_child(self, other, experiment, all_function_nodes, current_device): + def register_child( + self, other: CostModel, experiment: Experiment, all_function_nodes: List[FunctionRoot], current_device: Device + ) -> CostModel: """Registers a child node for the given model. Does not modify the stored model in self or other.""" diff --git a/discopop_library/discopop_optimizer/classes/nodes/SynchronizationTrigger.py b/discopop_library/discopop_optimizer/classes/nodes/SynchronizationTrigger.py index a372c0c13..89c62621b 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/SynchronizationTrigger.py +++ b/discopop_library/discopop_optimizer/classes/nodes/SynchronizationTrigger.py @@ -8,6 +8,7 @@ from typing import Optional, Set from sympy import Function, Symbol, Integer, Expr +from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.types.DataAccessType import WriteDataAccess # type: ignore from discopop_explorer.PEGraphX import NodeID @@ -20,7 +21,7 @@ class SynchronizationTrigger(Workload): def __init__( self, node_id: int, - experiment, + experiment: Experiment, cu_id: Optional[NodeID], sequential_workload: Optional[Expr], parallelizable_workload: Optional[Expr], diff --git a/discopop_library/discopop_optimizer/classes/nodes/Workload.py b/discopop_library/discopop_optimizer/classes/nodes/Workload.py index 9e24c093b..31ec9a0fb 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/Workload.py +++ b/discopop_library/discopop_optimizer/classes/nodes/Workload.py @@ -5,13 +5,20 @@ # This software may be modified and distributed under the terms of # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. +from __future__ import annotations from typing import Optional, Set, List, cast from sympy import Integer, Expr # type: ignore from discopop_explorer.PEGraphX import NodeID, PEGraphX, EdgeType from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from discopop_library.discopop_optimizer.Variables.Experiment import Experiment + from discopop_library.discopop_optimizer.classes.nodes.FunctionRoot import FunctionRoot from discopop_library.discopop_optimizer.classes.nodes.GenericNode import GenericNode +from discopop_library.discopop_optimizer.classes.system.devices.Device import Device from discopop_library.discopop_optimizer.classes.types.DataAccessType import ( WriteDataAccess, ReadDataAccess, @@ -28,7 +35,7 @@ class Workload(GenericNode): def __init__( self, node_id: int, - experiment, + experiment: Experiment, cu_id: Optional[NodeID], sequential_workload: Optional[Expr], parallelizable_workload: Optional[Expr], @@ -67,7 +74,9 @@ def get_hover_text(self) -> str: "Device ID: " + str(self.device_id) ) - def get_cost_model(self, experiment, all_function_nodes, current_device) -> CostModel: + def get_cost_model( + self, experiment: Experiment, all_function_nodes: List[FunctionRoot], current_device: Device + ) -> CostModel: """Performance model of a workload consists of the workload itself + the workload of called functions. Individual Workloads are assumed to be not parallelizable. Workloads of called functions are added as encountered. @@ -103,16 +112,15 @@ def get_cost_model(self, experiment, all_function_nodes, current_device) -> Cost return cm - def __get_costs_of_function_call(self, experiment, all_function_nodes, current_device) -> CostModel: + def __get_costs_of_function_call( + self, experiment: Experiment, all_function_nodes: List[FunctionRoot], current_device: Device + ) -> CostModel: """Check if the node performs a function call and returns the total costs for these.""" total_costs = CostModel(Integer(0), Integer(0)) # get CUIDs of called functions if self.original_cu_id is not None: called_cu_ids: List[str] = [ - str(t) - for s, t, d in cast(PEGraphX, experiment.detection_result.pet).out_edges( - self.original_cu_id, EdgeType.CALLSNODE - ) + str(t) for s, t, d in experiment.detection_result.pet.out_edges(self.original_cu_id, EdgeType.CALLSNODE) ] # filter for called FunctionRoots called_function_nodes = [fr for fr in all_function_nodes if str(fr.original_cu_id) in called_cu_ids] @@ -126,7 +134,9 @@ def __get_costs_of_function_call(self, experiment, all_function_nodes, current_d return total_costs - def register_child(self, other, experiment, all_function_nodes, current_device): + def register_child( + self, other: CostModel, experiment: Experiment, all_function_nodes: List[FunctionRoot], current_device: Device + ) -> CostModel: """Registers a child node for the given model. Does not modify the stored model in self or other.""" # since workloads do not modify their children, the performance model of other is simply added to self. diff --git a/discopop_library/discopop_optimizer/classes/system/Network.py b/discopop_library/discopop_optimizer/classes/system/Network.py index a32423c93..485dd5928 100644 --- a/discopop_library/discopop_optimizer/classes/system/Network.py +++ b/discopop_library/discopop_optimizer/classes/system/Network.py @@ -23,15 +23,15 @@ def __init__(self): self.__transfer_speeds = dict() self.__transfer_initialization_costs = dict() - def add_connection(self, source: Device, target: Device, transfer_speed: Expr, initialization_delay: Expr): + def add_connection(self, source: Device, target: Device, transfer_speed: Expr, initialization_delay: Expr) -> None: if source == target: transfer_speed = Integer(10000 * 1000) # 10000 GB/s = 10000 * 1000 MB/s self.__transfer_speeds[(source, target)] = transfer_speed self.__transfer_initialization_costs[(source, target)] = initialization_delay - def get_transfer_speed(self, source: Device, target: Device): + def get_transfer_speed(self, source: Device, target: Device) -> Expr: if source == target: - return Integer(1000000) # 1000 GB/s + return cast(Expr, Integer(1000000)) # 1000 GB/s if (source, target) not in self.__transfer_speeds: if self.__host_device is None: raise ValueError("Host device of network unspecified!") @@ -40,15 +40,15 @@ def get_transfer_speed(self, source: Device, target: Device): return min(S_to_H_speed, H_to_T_speed) return self.__transfer_speeds[(source, target)] - def get_transfer_initialization_costs(self, source: Device, target: Device): + def get_transfer_initialization_costs(self, source: Device, target: Device) -> Expr: if source == target: - return Integer(0) + return cast(Expr, Integer(0)) if (source, target) not in self.__transfer_speeds: if self.__host_device is None: raise ValueError("Host device of network unspecified!") S_to_H_init_costs = self.__transfer_initialization_costs[(source, self.__host_device)] H_to_T_init_costs = self.__transfer_initialization_costs[(self.__host_device, target)] - return S_to_H_init_costs + H_to_T_init_costs + return cast(Expr, S_to_H_init_costs + H_to_T_init_costs) return self.__transfer_initialization_costs[(source, target)] def get_free_symbols(self) -> List[Tuple[Symbol, Optional[Expr]]]: @@ -59,5 +59,5 @@ def get_free_symbols(self) -> List[Tuple[Symbol, Optional[Expr]]]: result_list += [(cast(Symbol, s), None) for s in expr.free_symbols] return result_list - def set_host_device(self, host_device: Device): + def set_host_device(self, host_device: Device) -> None: self.__host_device = host_device diff --git a/discopop_library/discopop_optimizer/classes/system/System.py b/discopop_library/discopop_optimizer/classes/system/System.py index ae87aed1d..3f8917f47 100644 --- a/discopop_library/discopop_optimizer/classes/system/System.py +++ b/discopop_library/discopop_optimizer/classes/system/System.py @@ -9,7 +9,7 @@ import os import pathlib import warnings -from typing import Any, Dict, List, Tuple, Optional +from typing import Any, Dict, List, Tuple, Optional, cast from sympy import Float, Symbol, Expr, Integer from discopop_library.discopop_optimizer.classes.enums.Distributions import FreeSymbolDistribution @@ -52,7 +52,7 @@ def __init__(self, arguments: OptimizerArguments): # todo: support the replication of device ids (e.g. CPU-0 and GPU-0) - def __build_from_configuration_file(self, arguments: OptimizerArguments): + def __build_from_configuration_file(self, arguments: OptimizerArguments) -> None: with open(arguments.system_configuration_path, "r") as f: system_configuration = json.load(f) self.__host_device_id = system_configuration["host_device"] @@ -87,7 +87,7 @@ def __build_from_configuration_file(self, arguments: OptimizerArguments): # no transfer speed information exists pass - def __build_CPU(self, device_configuration: Dict[str, Any]): + def __build_CPU(self, device_configuration: Dict[str, Any]) -> None: cpu = CPU( frequency=Integer(device_configuration["frequency"]), thread_count=Integer(device_configuration["threads"]), @@ -98,7 +98,7 @@ def __build_CPU(self, device_configuration: Dict[str, Any]): ) self.add_device(cpu, device_configuration["device_id"]) - def __build_GPU(self, device_configuration: Dict[str, Any]): + def __build_GPU(self, device_configuration: Dict[str, Any]) -> None: gpu = GPU( frequency=Integer(device_configuration["frequency"]), thread_count=Integer(device_configuration["threads"]), @@ -109,17 +109,19 @@ def __build_GPU(self, device_configuration: Dict[str, Any]): ) self.add_device(gpu, device_configuration["device_id"]) - def set_device_doall_overhead_model(self, device: Device, model: Expr, arguments: OptimizerArguments): + def set_device_doall_overhead_model(self, device: Device, model: Expr, arguments: OptimizerArguments) -> None: if arguments.verbose: print("System: Set DOALL overhead model: ", model) self.__device_do_all_overhead_models[device] = model - def set_device_doall_shared_overhead_model(self, device: Device, model: Expr, arguments: OptimizerArguments): + def set_device_doall_shared_overhead_model( + self, device: Device, model: Expr, arguments: OptimizerArguments + ) -> None: if arguments.verbose: print("System: Set DOALL SHARED overhead model: ", model) self.__device_do_all_shared_overhead_models[device] = model - def set_reduction_overhead_model(self, device: Device, model: Expr, arguments: OptimizerArguments): + def set_reduction_overhead_model(self, device: Device, model: Expr, arguments: OptimizerArguments) -> None: if arguments.verbose: print("System: Set REDUCTION overhead model: ", model) self.__device_reduction_overhead_models[device] = model @@ -128,24 +130,24 @@ def get_device_doall_overhead_model(self, device: Device, arguments: OptimizerAr if device not in self.__device_do_all_overhead_models: if arguments.verbose: warnings.warn("No DOALL overhead model, assuming 0 for device: " + str(device)) - return Expr(Integer(0)) + return cast(Expr, Integer(0)) return self.__device_do_all_overhead_models[device] def get_device_doall_shared_overhead_model(self, device: Device, arguments: OptimizerArguments) -> Expr: if device not in self.__device_do_all_shared_overhead_models: if arguments.verbose: warnings.warn("No DOALL SHARED overhead model, assuming 0 for device: " + str(device)) - return Expr(Integer(0)) + return cast(Expr, Integer(0)) return self.__device_do_all_shared_overhead_models[device] def get_device_reduction_overhead_model(self, device: Device, arguments: OptimizerArguments) -> Expr: if device not in self.__device_reduction_overhead_models: if arguments.verbose: warnings.warn("No REDUCTION overhead model, assuming 0 for device: " + str(device)) - return Expr(Integer(0)) + return cast(Expr, Integer(0)) return self.__device_reduction_overhead_models[device] - def add_device(self, device: Device, device_id: int): + def add_device(self, device: Device, device_id: int) -> None: self.__devices[device_id] = device def get_device(self, device_id: Optional[int]) -> Device: diff --git a/discopop_library/discopop_optimizer/classes/system/devices/CPU.py b/discopop_library/discopop_optimizer/classes/system/devices/CPU.py index f11efedcc..c78f279cb 100644 --- a/discopop_library/discopop_optimizer/classes/system/devices/CPU.py +++ b/discopop_library/discopop_optimizer/classes/system/devices/CPU.py @@ -6,6 +6,8 @@ # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. from typing import Dict + +from sympy import Integer from discopop_library.discopop_optimizer.classes.system.devices.Device import Device from discopop_library.discopop_optimizer.classes.system.devices.DeviceTypeEnum import DeviceTypeEnum @@ -13,8 +15,8 @@ class CPU(Device): def __init__( self, - frequency, - thread_count, + frequency: Integer, + thread_count: Integer, openmp_device_id: int, device_specific_compiler_flags: str, speedup: float, diff --git a/discopop_library/discopop_optimizer/classes/system/devices/Device.py b/discopop_library/discopop_optimizer/classes/system/devices/Device.py index 9be7ec5af..fb350c898 100644 --- a/discopop_library/discopop_optimizer/classes/system/devices/Device.py +++ b/discopop_library/discopop_optimizer/classes/system/devices/Device.py @@ -60,7 +60,7 @@ def get_free_symbols(self) -> List[Tuple[Symbol, Optional[Expr]]]: def get_measured_speedup(self) -> Expr: return Float(self.__speedup) - def get_estimated_execution_time_in_micro_seconds(self, workload: Expr, is_sequential: bool): + def get_estimated_execution_time_in_micro_seconds(self, workload: Optional[Expr], is_sequential: bool) -> Expr: """execution time is estimated by: - convert workload to estimated amount of CPU instructions using a extra-p model - NOTE: use "perf stat ./ define functions to evaluate workloads on different devices. include these functions in the construction of the cost model for later evaluation instead of "manually" converting the workload to time values # todo: correctly set is_sequential argument @@ -91,7 +93,7 @@ def get_estimated_execution_time_in_micro_seconds(self, workload: Expr, is_seque execution_time_in_seconds = workload_in_instructions / instructions_per_second execution_time_in_micro_seconds = execution_time_in_seconds * 1000000 - return execution_time_in_micro_seconds + return Float(execution_time_in_micro_seconds) def get_device_type(self) -> DeviceTypeEnum: raise ValueError("This method need to be overwritten by subclasses!") diff --git a/discopop_library/discopop_optimizer/classes/system/devices/GPU.py b/discopop_library/discopop_optimizer/classes/system/devices/GPU.py index f515b2ed8..edd9fa5ee 100644 --- a/discopop_library/discopop_optimizer/classes/system/devices/GPU.py +++ b/discopop_library/discopop_optimizer/classes/system/devices/GPU.py @@ -7,6 +7,8 @@ # directory for details. from typing import Dict, Tuple +from sympy import Integer + from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_library.discopop_optimizer.classes.system.devices.Device import Device from discopop_library.discopop_optimizer.classes.system.devices.DeviceTypeEnum import DeviceTypeEnum @@ -15,10 +17,10 @@ class GPU(Device): def __init__( self, - frequency, - thread_count, - openmp_device_id, - device_specific_compiler_flags, + frequency: Integer, + thread_count: Integer, + openmp_device_id: int, + device_specific_compiler_flags: str, speedup: float, compute_init_delays: Dict[str, float], ): diff --git a/discopop_library/discopop_optimizer/classes/system/system_utils.py b/discopop_library/discopop_optimizer/classes/system/system_utils.py index fc76c9899..2baa629ed 100644 --- a/discopop_library/discopop_optimizer/classes/system/system_utils.py +++ b/discopop_library/discopop_optimizer/classes/system/system_utils.py @@ -17,7 +17,7 @@ from discopop_library.discopop_optimizer.classes.system.devices.GPU import GPU -def generate_default_system_configuration(file_path: str): +def generate_default_system_configuration(file_path: str) -> None: """Generates a system configuration file using the default values if none exists so far.""" if os.path.exists(file_path): return diff --git a/discopop_library/discopop_optimizer/gui/plotting/CostModels.py b/discopop_library/discopop_optimizer/gui/plotting/CostModels.py index 084fdaf6a..c17c21db7 100644 --- a/discopop_library/discopop_optimizer/gui/plotting/CostModels.py +++ b/discopop_library/discopop_optimizer/gui/plotting/CostModels.py @@ -21,14 +21,14 @@ def plot_CostModels( - experiment, + experiment: Experiment, models: List[CostModel], sorted_free_symbols: List[Symbol], free_symbol_ranges: Dict[Symbol, Tuple[float, float]], labels: Optional[List[str]] = None, title: Optional[str] = None, super_title: Optional[str] = None, -): +) -> None: local_sorted_free_symbols = copy.deepcopy(sorted_free_symbols) local_free_symbol_ranges = copy.deepcopy(free_symbol_ranges) for symbol in experiment.substitutions: @@ -112,7 +112,7 @@ def plot_CostModels_using_function_path_selections( labels: Optional[List[str]] = None, title: Optional[str] = None, super_title: Optional[str] = None, -): +) -> None: # apply selected substitutions # collect substitutions local_substitutions = copy.deepcopy(experiment.substitutions) @@ -188,7 +188,7 @@ def plot_CostModels_using_function_path_selections( print("Plotiting not supported for", len(local_sorted_free_symbols), "free symbols!") -def print_current_function_path_selections(experiment: Experiment): +def print_current_function_path_selections(experiment: Experiment) -> None: """Prints an overview of the currently selected paths for each function to the console""" print("###") print("SELECTIONS:") @@ -198,7 +198,7 @@ def print_current_function_path_selections(experiment: Experiment): print("###") -def print_current_substitutions(experiment: Experiment): +def print_current_substitutions(experiment: Experiment) -> None: """Prints an overview of the currently selected paths for each function to the console""" print("###") print("SUBSTITUTIONS:") @@ -216,7 +216,7 @@ def print_simplified_function( labels: Optional[List[str]] = None, title: Optional[str] = None, super_title: Optional[str] = None, -): +) -> None: """Prints an simplified mathematical function based on the current set of selections""" # todo: NOTE: copied from plot_CostModels_using_function_path_selections @@ -288,7 +288,7 @@ def __1d_plot( labels: Optional[List[str]] = None, title: Optional[str] = None, super_title: Optional[str] = None, -): +) -> None: global __unique_plot_id matplotlib.use("TkAgg") # Make a dataset from models: @@ -329,7 +329,7 @@ def __2d_plot( free_symbol_ranges: Dict[Symbol, Tuple[float, float]], labels: Optional[List[str]] = None, title: Optional[str] = None, -): +) -> None: matplotlib.use("TkAgg") combined_plot = None for idx, model in enumerate(models): @@ -375,7 +375,7 @@ def __3d_plot( free_symbol_ranges: Dict[Symbol, Tuple[float, float]], labels: Optional[List[str]] = None, title: Optional[str] = None, -): +) -> None: matplotlib.use("TkAgg") combined_plot = None for idx, model in enumerate(models): diff --git a/discopop_library/discopop_optimizer/gui/presentation/ChoiceDetails.py b/discopop_library/discopop_optimizer/gui/presentation/ChoiceDetails.py index 7f9b7398f..d17e80ec1 100644 --- a/discopop_library/discopop_optimizer/gui/presentation/ChoiceDetails.py +++ b/discopop_library/discopop_optimizer/gui/presentation/ChoiceDetails.py @@ -16,7 +16,7 @@ from DEPRECATED_discopop_wizard.screens.widgets.ScrollableText import ScrollableTextWidget -def display_choices_for_model(graph: nx.DiGraph, model: CostModel, window_title: Optional[str] = None): +def display_choices_for_model(graph: nx.DiGraph, model: CostModel, window_title: Optional[str] = None) -> None: root = Tk() if window_title is not None: root.configure() diff --git a/discopop_library/discopop_optimizer/gui/presentation/OptionTable.py b/discopop_library/discopop_optimizer/gui/presentation/OptionTable.py index 19a7887df..0a642c4c0 100644 --- a/discopop_library/discopop_optimizer/gui/presentation/OptionTable.py +++ b/discopop_library/discopop_optimizer/gui/presentation/OptionTable.py @@ -44,7 +44,7 @@ def show_options( function_root: FunctionRoot, parent_frame: tkinter.Frame, spawned_windows: List[tkinter.Toplevel], - window_title=None, + window_title: Optional[str] = None, ) -> List[Tuple[CostModel, ContextObject, str]]: """Shows a tkinter table to browse and plot models""" # root = tkinter.Toplevel() @@ -240,7 +240,7 @@ def __save_models( experiment: Experiment, function_root: FunctionRoot, options: List[Tuple[CostModel, ContextObject, str]], -): +) -> None: print("SAVE: ", function_root) print("\ttype; ", type(function_root)) experiment.function_models[function_root] = options @@ -259,7 +259,7 @@ def add_random_models( function_root: FunctionRoot, parent_frame: Optional[tkinter.Frame], spawned_windows: List[tkinter.Toplevel], - window_title=None, + window_title: Optional[str] = None, show_results: bool = True, ) -> List[Tuple[CostModel, ContextObject, str]]: if root is not None: diff --git a/discopop_library/discopop_optimizer/gui/widgets/ScrollableFrame.py b/discopop_library/discopop_optimizer/gui/widgets/ScrollableFrame.py index b68fe4626..6c9ced61a 100644 --- a/discopop_library/discopop_optimizer/gui/widgets/ScrollableFrame.py +++ b/discopop_library/discopop_optimizer/gui/widgets/ScrollableFrame.py @@ -35,7 +35,7 @@ def __init__(self, parent_frame): self.canvas.configure(yscrollcommand=self.scrollbar.set) - def finalize(self, row_count: int, row: int = 0, col: int = 0, rowspan: int = 1, columnspan: int = 1): + def finalize(self, row_count: int, row: int = 0, col: int = 0, rowspan: int = 1, columnspan: int = 1) -> None: if rowspan < 1: rowspan = 1 if columnspan < 1: diff --git a/discopop_library/discopop_optimizer/interactive/interactive_optimizer.py b/discopop_library/discopop_optimizer/interactive/interactive_optimizer.py index bec28f2c3..fbc0b2d21 100644 --- a/discopop_library/discopop_optimizer/interactive/interactive_optimizer.py +++ b/discopop_library/discopop_optimizer/interactive/interactive_optimizer.py @@ -28,7 +28,7 @@ logger = logging.getLogger("Optimizer").getChild("Interactive") -def run_interactive_optimizer(arguments: OptimizerArguments): +def run_interactive_optimizer(arguments: OptimizerArguments) -> None: logger.setLevel(arguments.log_level) logger.info("Starting..") # check prerequisites @@ -62,7 +62,9 @@ def run_interactive_optimizer(arguments: OptimizerArguments): logger.info("Closing interactive optimizer..") -def parse_interactive_export(experiment: Experiment, applied_suggestions: Set[int], arguments: OptimizerArguments): +def parse_interactive_export( + experiment: Experiment, applied_suggestions: Set[int], arguments: OptimizerArguments +) -> None: parse_input( input="add " + arguments.interactive_export.replace(",", " "), experiment=experiment, @@ -72,7 +74,9 @@ def parse_interactive_export(experiment: Experiment, applied_suggestions: Set[in parse_input(input="export", experiment=experiment, applied_suggestions=applied_suggestions, arguments=arguments) -def parse_input(input: str, experiment: Experiment, applied_suggestions: Set[int], arguments: OptimizerArguments): +def parse_input( + input: str, experiment: Experiment, applied_suggestions: Set[int], arguments: OptimizerArguments +) -> bool: """Return True if the interactive session should be kept alive. Return False if the main loop should be exited.""" if input.startswith("list"): @@ -115,12 +119,12 @@ def parse_input(input: str, experiment: Experiment, applied_suggestions: Set[int return True -def show_configuration_diff(experiment: Experiment, applied_suggestions: Set[int]): +def show_configuration_diff(experiment: Experiment, applied_suggestions: Set[int]) -> None: logger.info("Creating and showing the diff for the current configuration..") logger.info("Not yet implemented") -def export_configuration(experiment: Experiment, applied_suggestions: Set[int], arguments: OptimizerArguments): +def export_configuration(experiment: Experiment, applied_suggestions: Set[int], arguments: OptimizerArguments) -> None: logger.info("Exporting the current configuration..") configured_pattern = __create_optimizer_output_pattern(experiment, applied_suggestions) if configured_pattern is None: diff --git a/discopop_library/discopop_optimizer/optimization/evaluate_all_decision_combinations.py b/discopop_library/discopop_optimizer/optimization/evaluate_all_decision_combinations.py index 345e4cdf9..e6f05333e 100644 --- a/discopop_library/discopop_optimizer/optimization/evaluate_all_decision_combinations.py +++ b/discopop_library/discopop_optimizer/optimization/evaluate_all_decision_combinations.py @@ -10,7 +10,7 @@ import os from typing import Dict, List, Optional, Set, Tuple, cast -from sympy import Expr +from sympy import Expr, re import tqdm # type: ignore from discopop_explorer.PEGraphX import NodeID # type: ignore @@ -129,14 +129,14 @@ def evaluate_all_decision_combinations( def __initialize_worker( experiment: Experiment, arguments: OptimizerArguments, -): +) -> None: global global_experiment global global_arguments global_experiment = experiment global_arguments = arguments -def __evaluate_configuration(param_tuple): +def __evaluate_configuration(param_tuple: List[int]) -> Tuple[Tuple[int, ...], Expr, ContextObject]: global global_experiment global global_arguments if global_experiment is None: @@ -163,7 +163,7 @@ def __dump_result_to_file_using_pattern_ids( for pattern_id in experiment.suggestion_to_node_ids_dict: if entry in experiment.suggestion_to_node_ids_dict[pattern_id]: new_key.append(str(pattern_id) + "@" + str(data_at(experiment.optimization_graph, entry).device_id)) - dumpable_dict[str(new_key)] = str(int(float(str(costs_dict[key].evalf())))) + dumpable_dict[str(new_key)] = str(int(float(str(re(costs_dict[key].evalf()))))) dump_path: str = os.path.join(optimizer_dir, "exhaustive_results.json") with open(dump_path, "w") as fp: diff --git a/discopop_library/discopop_optimizer/optimization/evolutionary_algorithm.py b/discopop_library/discopop_optimizer/optimization/evolutionary_algorithm.py index e96edfb92..bc4dbe250 100644 --- a/discopop_library/discopop_optimizer/optimization/evolutionary_algorithm.py +++ b/discopop_library/discopop_optimizer/optimization/evolutionary_algorithm.py @@ -122,14 +122,14 @@ def __calculate_fitness( def __initialize_fitness_worker( experiment: Experiment, arguments: OptimizerArguments, -): +) -> None: global global_experiment global global_arguments global_experiment = experiment global_arguments = arguments -def __get_score(param_tuple) -> Tuple[List[int], int, ContextObject]: +def __get_score(param_tuple: List[int]) -> Tuple[List[int], int, ContextObject]: global global_experiment global global_arguments configuration = param_tuple @@ -151,7 +151,7 @@ def __print_population( population: List[List[int]], fitness: List[int], arguments: OptimizerArguments, -): +) -> None: sorted_fitness = sorted(enumerate(fitness), key=lambda x: x[1], reverse=True) print("# POPULATION") for fitness_idx, fitness_value in sorted_fitness: @@ -181,7 +181,7 @@ def __initialize_fill_worker( experiment: Experiment, available_decisions: Dict[FunctionRoot, List[List[int]]], arguments: OptimizerArguments, -): +) -> None: global global_experiment global global_arguments global global_available_decisions @@ -246,7 +246,7 @@ def __select( population: List[List[int]], fitness: List[int], new_population_size: int, -): +) -> List[List[int]]: """Performs a fitness-proportionate Selection""" # get Sum of scores score_sum = 0.0 @@ -276,7 +276,7 @@ def __crossover( arguments: OptimizerArguments, population: List[List[int]], crossovers: int, -): +) -> List[List[int]]: global global_experiment global global_arguments global global_population @@ -305,7 +305,9 @@ def __crossover( return population -def __initialize_crossover_worker(experiment: Experiment, arguments: OptimizerArguments, population: List[List[int]]): +def __initialize_crossover_worker( + experiment: Experiment, arguments: OptimizerArguments, population: List[List[int]] +) -> None: global global_experiment global global_arguments global global_population @@ -314,7 +316,9 @@ def __initialize_crossover_worker(experiment: Experiment, arguments: OptimizerAr global_population = population -def __parallel_crossover(param_tuple): +def __parallel_crossover( + param_tuple: None, +) -> Optional[Tuple[Tuple[List[int], List[int]], Tuple[List[int], List[int]]]]: global global_experiment global global_arguments global global_population @@ -378,7 +382,9 @@ def __mutate( return population -def __initialize_mutate_worker(experiment: Experiment, arguments: OptimizerArguments, population: List[List[int]]): +def __initialize_mutate_worker( + experiment: Experiment, arguments: OptimizerArguments, population: List[List[int]] +) -> None: global global_experiment global global_arguments global global_population @@ -490,7 +496,7 @@ def __get_random_configuration( experiment: Experiment, available_decisions: Dict[FunctionRoot, List[List[int]]], arguments: OptimizerArguments, -): +) -> List[int]: while True: random_configuration: List[int] = [] # fill configuration diff --git a/discopop_library/discopop_optimizer/optimization/greedy.py b/discopop_library/discopop_optimizer/optimization/greedy.py index c33882c2f..710c52f4e 100644 --- a/discopop_library/discopop_optimizer/optimization/greedy.py +++ b/discopop_library/discopop_optimizer/optimization/greedy.py @@ -169,14 +169,14 @@ def __get_dicision_list(decisions_dict): def __initialize_cost_caluclation_worker( experiment: Experiment, arguments: OptimizerArguments, -): +) -> None: global global_experiment global global_arguments global_experiment = experiment global_arguments = arguments -def __get_score(param_tuple) -> Tuple[Dict[int, List[List[int]]], int, ContextObject]: +def __get_score(param_tuple: Dict[int, List[List[int]]]) -> Tuple[Dict[int, List[List[int]]], int, ContextObject]: global global_experiment global global_arguments configuration = param_tuple diff --git a/discopop_library/discopop_optimizer/optimizer.py b/discopop_library/discopop_optimizer/optimizer.py index 243c739e8..adcb0b952 100644 --- a/discopop_library/discopop_optimizer/optimizer.py +++ b/discopop_library/discopop_optimizer/optimizer.py @@ -76,14 +76,14 @@ from ..HostpotLoader.hostpot_loader import run as load_hotspots -def run(arguments: OptimizerArguments): +def run(arguments: OptimizerArguments) -> None: if arguments.interactive: run_interactive_optimizer(arguments) else: run_passive_optimizer(arguments) -def run_passive_optimizer(arguments: OptimizerArguments): +def run_passive_optimizer(arguments: OptimizerArguments) -> None: logger = logging.getLogger("Optimizer") # check prerequisites and setup folder structure diff --git a/discopop_library/discopop_optimizer/scheduling/workload_delta.py b/discopop_library/discopop_optimizer/scheduling/workload_delta.py index dbc22f776..c28e6c21b 100644 --- a/discopop_library/discopop_optimizer/scheduling/workload_delta.py +++ b/discopop_library/discopop_optimizer/scheduling/workload_delta.py @@ -116,7 +116,7 @@ def aggregate(self): cur_elem = cur_elem[index] cur_elem[indices[-1]] = RegularCosts((min_wl, max_wl)) - def register_workload(self, min_wl: int, max_wl: int): + def register_workload(self, min_wl: int, max_wl: int) -> None: # get the innermost workload stack innermost_stack, _ = self.__get_innermost_workload_stack() innermost_stack.append(RegularCosts((min_wl, max_wl))) diff --git a/discopop_library/discopop_optimizer/suggestions/importers/do_all.py b/discopop_library/discopop_optimizer/suggestions/importers/do_all.py index 8b30e5715..c5b95fa26 100644 --- a/discopop_library/discopop_optimizer/suggestions/importers/do_all.py +++ b/discopop_library/discopop_optimizer/suggestions/importers/do_all.py @@ -7,7 +7,7 @@ # directory for details. import copy import logging -from typing import Set, cast, Tuple, List, Dict +from typing import Callable, Set, cast, Tuple, List, Dict import networkx as nx # type: ignore from sympy import Expr, Integer, Symbol, log, Float, init_printing @@ -35,7 +35,7 @@ def import_suggestion( - graph: nx.DiGraph, suggestion, get_next_free_node_id_function, environment: Experiment + graph: nx.DiGraph, suggestion: DoAllInfo, get_next_free_node_id_function: Callable[[], int], environment: Experiment ) -> nx.DiGraph: # find a node which belongs to the suggestion buffer = [n for n in graph.nodes] diff --git a/discopop_library/discopop_optimizer/suggestions/importers/reduction.py b/discopop_library/discopop_optimizer/suggestions/importers/reduction.py index 936093171..d76072494 100644 --- a/discopop_library/discopop_optimizer/suggestions/importers/reduction.py +++ b/discopop_library/discopop_optimizer/suggestions/importers/reduction.py @@ -6,11 +6,12 @@ # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. import copy -from typing import Set, cast, Tuple, List, Dict +from typing import Callable, Set, cast, Tuple, List, Dict import networkx as nx # type: ignore from sympy import Expr, Integer, Symbol, log, Float, init_printing # type: ignore +from discopop_explorer.pattern_detectors.reduction_detector import ReductionInfo from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel from discopop_library.discopop_optimizer.Microbench.utils import ( convert_discopop_to_microbench_workload, @@ -28,7 +29,10 @@ def import_suggestion( - graph: nx.DiGraph, suggestion, get_next_free_node_id_function, environment: Experiment + graph: nx.DiGraph, + suggestion: ReductionInfo, + get_next_free_node_id_function: Callable[[], int], + environment: Experiment, ) -> nx.DiGraph: # find a node which belongs to the suggestion buffer = [n for n in graph.nodes] diff --git a/discopop_library/discopop_optimizer/utilities/MOGUtilities.py b/discopop_library/discopop_optimizer/utilities/MOGUtilities.py index 2d1bba9f5..c17cc47f3 100644 --- a/discopop_library/discopop_optimizer/utilities/MOGUtilities.py +++ b/discopop_library/discopop_optimizer/utilities/MOGUtilities.py @@ -129,7 +129,7 @@ def get_function_return_node(graph: nx.DiGraph, function: int) -> int: def show_decision_graph( graph: nx.DiGraph, decisions: List[int], show_dataflow: bool = True, show_mutex_edges: bool = False -): +) -> None: print("Decisions: ", decisions) contained_nodes: Set[int] = set() for function in get_all_function_nodes(graph): @@ -167,7 +167,9 @@ def show_decision_graph( show(graph.subgraph(contained_nodes), show_dataflow=show_dataflow, show_mutex_edges=show_mutex_edges) -def show_function(graph: nx.DiGraph, function: FunctionRoot, show_dataflow: bool = True, show_mutex_edges: bool = True): +def show_function( + graph: nx.DiGraph, function: FunctionRoot, show_dataflow: bool = True, show_mutex_edges: bool = True +) -> None: # get nodes in subtree of function contained_nodes: Set[int] = set() queue: List[int] = [function.node_id] @@ -181,7 +183,7 @@ def show_function(graph: nx.DiGraph, function: FunctionRoot, show_dataflow: bool show(graph.subgraph(contained_nodes), show_dataflow=show_dataflow, show_mutex_edges=show_mutex_edges) -def show(graph: nx.DiGraph, show_dataflow: bool = True, show_mutex_edges: bool = True): +def show(graph: nx.DiGraph, show_dataflow: bool = True, show_mutex_edges: bool = True) -> None: """Plots the graph :return: @@ -376,32 +378,32 @@ def hover(event): plt.show() -def add_successor_edge(graph: nx.DiGraph, source_id: int, target_id: int): +def add_successor_edge(graph: nx.DiGraph, source_id: int, target_id: int) -> None: edge_data = SuccessorEdge() graph.add_edge(source_id, target_id, data=edge_data) -def add_child_edge(graph: nx.DiGraph, source_id: int, target_id: int): +def add_child_edge(graph: nx.DiGraph, source_id: int, target_id: int) -> None: edge_data = ChildEdge() graph.add_edge(source_id, target_id, data=edge_data) -def add_call_edge(graph: nx.DiGraph, source_id: int, target_id: int): +def add_call_edge(graph: nx.DiGraph, source_id: int, target_id: int) -> None: edge_data = CallEdge() graph.add_edge(source_id, target_id, data=edge_data) -def add_temporary_edge(graph: nx.DiGraph, source_id: int, target_id: int): +def add_temporary_edge(graph: nx.DiGraph, source_id: int, target_id: int) -> None: edge_data = TemporaryEdge() graph.add_edge(source_id, target_id, data=edge_data) -def add_dataflow_edge(graph: nx.DiGraph, source_id: int, target_id: int): +def add_dataflow_edge(graph: nx.DiGraph, source_id: int, target_id: int) -> None: edge_data = DataFlowEdge() graph.add_edge(source_id, target_id, data=edge_data) -def delete_outgoing_temporary_edges(graph: nx.DiGraph, source_id: int): +def delete_outgoing_temporary_edges(graph: nx.DiGraph, source_id: int) -> None: to_be_deleted = set() for edge in graph.out_edges(source_id): edge_data = graph.edges[edge]["data"] @@ -417,17 +419,17 @@ def redirect_edge( new_source_id: int, old_target_id: int, new_target_id: int, -): +) -> None: edge_data = graph.edges[(old_source_id, old_target_id)]["data"] remove_edge(graph, old_source_id, old_target_id) graph.add_edge(new_source_id, new_target_id, data=edge_data) -def remove_edge(graph: nx.DiGraph, source_id: int, target_id: int): +def remove_edge(graph: nx.DiGraph, source_id: int, target_id: int) -> None: graph.remove_edge(source_id, target_id) -def convert_temporary_edges(graph: nx.DiGraph): +def convert_temporary_edges(graph: nx.DiGraph) -> None: """Convert temporary edges to Successor edges""" for edge in graph.edges: edge_data = graph.edges[edge]["data"] @@ -435,7 +437,7 @@ def convert_temporary_edges(graph: nx.DiGraph): graph.edges[edge]["data"] = edge_data.convert_to_successor_edge() -def convert_temporary_edge(graph: nx.DiGraph, source_id: int, target_id: int): +def convert_temporary_edge(graph: nx.DiGraph, source_id: int, target_id: int) -> None: """Converts a single temporary edge to a successor edge""" edge_data = graph.edges[(source_id, target_id)]["data"] if isinstance(edge_data, TemporaryEdge): @@ -611,7 +613,7 @@ def get_available_decisions_for_functions( return available_decisions -def __initialize_availability_worker(graph: nx.DiGraph, arguments: OptimizerArguments): +def __initialize_availability_worker(graph: nx.DiGraph, arguments: OptimizerArguments) -> None: global global_graph global global_arguments global_graph = graph @@ -622,7 +624,7 @@ def __parallel_get_decisions_from_node_recursive(function_node): global global_graph global global_arguments - def get_decisions_from_node_recursive(node_id, prev_decisions: List[int]) -> List[List[int]]: + def get_decisions_from_node_recursive(node_id: int, prev_decisions: List[int]) -> List[List[int]]: children_paths: List[List[int]] = [] # get decisions from children for child in get_children(global_graph, node_id): diff --git a/discopop_library/discopop_optimizer/utilities/insert_device_switch_nodes.py b/discopop_library/discopop_optimizer/utilities/insert_device_switch_nodes.py index ba9390231..626a13f45 100644 --- a/discopop_library/discopop_optimizer/utilities/insert_device_switch_nodes.py +++ b/discopop_library/discopop_optimizer/utilities/insert_device_switch_nodes.py @@ -102,7 +102,7 @@ def insert_device_switch_nodes(experiment: Experiment) -> nx.DiGraph: return experiment.optimization_graph -def __set_read_and_write_information(experiment: Experiment, device_switch_nodes: List[int]): +def __set_read_and_write_information(experiment: Experiment, device_switch_nodes: List[int]) -> None: """Collect and set read and write information for the device switch nodes""" for node in device_switch_nodes: # look ahead to next device switch along each path and collect the encountered reads and writes diff --git a/discopop_library/discopop_optimizer/utilities/optimization/GlobalOptimization/RandomSamples.py b/discopop_library/discopop_optimizer/utilities/optimization/GlobalOptimization/RandomSamples.py index 17a7b2189..04c26e4d2 100644 --- a/discopop_library/discopop_optimizer/utilities/optimization/GlobalOptimization/RandomSamples.py +++ b/discopop_library/discopop_optimizer/utilities/optimization/GlobalOptimization/RandomSamples.py @@ -30,7 +30,13 @@ def find_quasi_optimal_using_random_samples( free_symbol_ranges: Dict[Symbol, Tuple[float, float]], free_symbol_distributions: Dict[Symbol, FreeSymbolDistribution], verbose: bool = False, -): +) -> Tuple[ + Tuple[CostModel, ContextObject], + Tuple[CostModel, ContextObject], + Tuple[CostModel, ContextObject], + Tuple[CostModel, ContextObject], + Tuple[CostModel, ContextObject], +]: """Returns the identified minimum, maximum, median, 25% quartile and 75% quartile of the random_path_count samples. NOTE: The decisions should be treated as suggestions, not mathematically accurate decisions due to the used comparison method!""" diff --git a/discopop_library/discopop_optimizer/utilities/visualization/update_graph.py b/discopop_library/discopop_optimizer/utilities/visualization/update_graph.py index 2017eed2f..7e9f5ace2 100644 --- a/discopop_library/discopop_optimizer/utilities/visualization/update_graph.py +++ b/discopop_library/discopop_optimizer/utilities/visualization/update_graph.py @@ -29,7 +29,7 @@ from discopop_library.result_classes.OptimizerOutputPattern import OptimizerOutputPattern # type: ignore -def show_update_graph(graph, configuration: OptimizerOutputPattern, experiment: Experiment): +def show_update_graph(graph: nx.DiGraph, configuration: OptimizerOutputPattern, experiment: Experiment) -> None: matplotlib.use("TkAgg") fig, ax = plt.subplots() try: diff --git a/discopop_library/result_classes/OptimizerOutputPattern.py b/discopop_library/result_classes/OptimizerOutputPattern.py index df75e6edd..0aabcdf24 100644 --- a/discopop_library/result_classes/OptimizerOutputPattern.py +++ b/discopop_library/result_classes/OptimizerOutputPattern.py @@ -35,7 +35,7 @@ def __init__(self, node: Node, decisions: List[int], host_device_id: int, experi self.host_device_id = host_device_id experiment.pattern_id_to_decisions_dict[self.pattern_id] = decisions - def reconstruct_from_file(self, file_path: str): # todo remove? + def reconstruct_from_file(self, file_path: str) -> None: # todo remove? with open(file_path, "r") as f: loaded_data = json.load(f) self.applied_patterns = loaded_data["applied_patterns"] @@ -45,7 +45,7 @@ def reconstruct_from_file(self, file_path: str): # todo remove? for values in loaded_data["data_movement"]: self.data_movement.append(construct_update_from_dict(values)) - def dump_to_file(self, file_path: str): # todo remove? + def dump_to_file(self, file_path: str) -> None: # todo remove? dumpable_dict: Dict[str, Any] = dict() dumpable_dict["applied_patterns"] = self.applied_patterns dumpable_dict["data_movement"] = [update.toDict() for update in self.data_movement] @@ -55,14 +55,14 @@ def dump_to_file(self, file_path: str): # todo remove? with open(file_path, "w") as f: json.dump(dumpable_dict, f) - def add_pattern(self, pattern_id: SuggestionId, target_device_id: DeviceID, device_type: DeviceTypeEnum): + def add_pattern(self, pattern_id: SuggestionId, target_device_id: DeviceID, device_type: DeviceTypeEnum) -> None: if self.pattern_id is None: # get a unique pattern_id self.pattern_id = get_unique_pattern_id() tmp_dict = {"pattern_id": pattern_id, "device_id": target_device_id, "device_type": device_type} self.applied_patterns.append(tmp_dict) - def add_data_movement(self, update: Update): + def add_data_movement(self, update: Update) -> None: self.data_movement.append(update) def get_contained_decisions(self, experiment: Experiment) -> List[int]: diff --git a/test/end_to_end/do_all/calls/complex/src/FileMapping.txt b/test/end_to_end/do_all/calls/complex/src/FileMapping.txt new file mode 100644 index 000000000..e77368562 --- /dev/null +++ b/test/end_to_end/do_all/calls/complex/src/FileMapping.txt @@ -0,0 +1 @@ +1 /home/lukas/git/discopop/test/end_to_end/do_all/calls/complex/src/code.cpp diff --git a/test/end_to_end/do_all/calls/complex/src/code.ll b/test/end_to_end/do_all/calls/complex/src/code.ll new file mode 100644 index 000000000..c6ad70045 --- /dev/null +++ b/test/end_to_end/do_all/calls/complex/src/code.ll @@ -0,0 +1,780 @@ +; ModuleID = 'code.cpp' +source_filename = "code.cpp" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@_ZZ4mainE1n = internal global i32 5000, align 4, !dbg !0 +@_ZZ4mainE1a = internal global double 2.000000e+00, align 8, !dbg !17 +@.str = private unnamed_addr constant [5 x i8] c"base\00", align 1 +@.str.1 = private unnamed_addr constant [9 x i8] c"offset_1\00", align 1 +@.str.2 = private unnamed_addr constant [9 x i8] c"offset_2\00", align 1 +@.str.3 = private unnamed_addr constant [6 x i8] c"index\00", align 1 +@.str.4 = private unnamed_addr constant [2 x i8] c"n\00", align 1 +@.str.5 = private unnamed_addr constant [10 x i8] c"1:19;1:20\00", align 1 +@.str.6 = private unnamed_addr constant [10 x i8] c"1:19;1:22\00", align 1 +@.str.7 = private unnamed_addr constant [10 x i8] c"1:24;1:25\00", align 1 +@.str.8 = private unnamed_addr constant [10 x i8] c"1:24;1:28\00", align 1 +@.str.9 = private unnamed_addr constant [10 x i8] c"1:30;1:31\00", align 1 +@.str.10 = private unnamed_addr constant [10 x i8] c"1:30;1:34\00", align 1 +@.str.11 = private unnamed_addr constant [12 x i8] c"_ZZ4mainE1n\00", align 1 +@.str.12 = private unnamed_addr constant [12 x i8] c"_ZZ4mainE1a\00", align 1 +@.str.13 = private unnamed_addr constant [5 x i8] c".str\00", align 1 +@.str.14 = private unnamed_addr constant [7 x i8] c".str.1\00", align 1 +@.str.15 = private unnamed_addr constant [7 x i8] c".str.2\00", align 1 +@.str.16 = private unnamed_addr constant [7 x i8] c".str.3\00", align 1 +@.str.17 = private unnamed_addr constant [7 x i8] c".str.4\00", align 1 +@.str.18 = private unnamed_addr constant [7 x i8] c".str.5\00", align 1 +@.str.19 = private unnamed_addr constant [7 x i8] c".str.6\00", align 1 +@.str.20 = private unnamed_addr constant [7 x i8] c".str.7\00", align 1 +@.str.21 = private unnamed_addr constant [7 x i8] c".str.8\00", align 1 +@.str.22 = private unnamed_addr constant [7 x i8] c".str.9\00", align 1 +@.str.23 = private unnamed_addr constant [7 x i8] c"retval\00", align 1 +@.str.24 = private unnamed_addr constant [5 x i8] c"argc\00", align 1 +@.str.25 = private unnamed_addr constant [5 x i8] c"argv\00", align 1 +@.str.26 = private unnamed_addr constant [2 x i8] c"x\00", align 1 +@.str.27 = private unnamed_addr constant [2 x i8] c"i\00", align 1 + +; Function Attrs: noinline nounwind optnone uwtable +define void @_Z19perform_calculationPdii(double* %base, i32 %offset_1, i32 %offset_2) #0 !dbg !265 { +entry: + call void @__dp_func_entry(i32 16388, i32 0) + %base.addr = alloca double*, align 8 + %0 = ptrtoint double** %base.addr to i64 + %offset_1.addr = alloca i32, align 4 + %1 = ptrtoint i32* %offset_1.addr to i64 + %offset_2.addr = alloca i32, align 4 + %2 = ptrtoint i32* %offset_2.addr to i64 + %3 = ptrtoint double** %base.addr to i64 + store double* %base, double** %base.addr, align 8 + call void @llvm.dbg.declare(metadata double** %base.addr, metadata !268, metadata !DIExpression()), !dbg !269 + %4 = ptrtoint i32* %offset_1.addr to i64 + store i32 %offset_1, i32* %offset_1.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %offset_1.addr, metadata !270, metadata !DIExpression()), !dbg !271 + %5 = ptrtoint i32* %offset_2.addr to i64 + store i32 %offset_2, i32* %offset_2.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %offset_2.addr, metadata !272, metadata !DIExpression()), !dbg !273 + %6 = ptrtoint double** %base.addr to i64 + %7 = load double*, double** %base.addr, align 8, !dbg !274 + %8 = ptrtoint i32* %offset_2.addr to i64 + %9 = load i32, i32* %offset_2.addr, align 4, !dbg !275 + %idxprom = sext i32 %9 to i64, !dbg !274 + %arrayidx = getelementptr inbounds double, double* %7, i64 %idxprom, !dbg !274 + %10 = ptrtoint double* %arrayidx to i64 + call void @__dp_read(i32 16388, i64 %10, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i32 0, i32 0)) + %11 = load double, double* %arrayidx, align 8, !dbg !274 + %add = fadd double 4.200000e+01, %11, !dbg !276 + %12 = ptrtoint double** %base.addr to i64 + %13 = load double*, double** %base.addr, align 8, !dbg !277 + %14 = ptrtoint i32* %offset_1.addr to i64 + %15 = load i32, i32* %offset_1.addr, align 4, !dbg !278 + %idxprom1 = sext i32 %15 to i64, !dbg !277 + %arrayidx2 = getelementptr inbounds double, double* %13, i64 %idxprom1, !dbg !277 + %16 = ptrtoint double* %arrayidx2 to i64 + call void @__dp_write(i32 16388, i64 %16, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i32 0, i32 0)) + store double %add, double* %arrayidx2, align 8, !dbg !279 + call void @__dp_report_bb(i32 0) + call void @__dp_func_exit(i32 16388, i32 0), !dbg !280 + ret void, !dbg !280 +} + +; Function Attrs: nounwind readnone speculatable willreturn +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +; Function Attrs: noinline nounwind optnone uwtable +define void @_Z14doall_possiblePdi(double* %base, i32 %index) #0 !dbg !281 { +entry: + call void @__dp_func_entry(i32 16390, i32 0) + %base.addr = alloca double*, align 8 + %0 = ptrtoint double** %base.addr to i64 + %index.addr = alloca i32, align 4 + %1 = ptrtoint i32* %index.addr to i64 + %2 = ptrtoint double** %base.addr to i64 + store double* %base, double** %base.addr, align 8 + call void @llvm.dbg.declare(metadata double** %base.addr, metadata !284, metadata !DIExpression()), !dbg !285 + %3 = ptrtoint i32* %index.addr to i64 + store i32 %index, i32* %index.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %index.addr, metadata !286, metadata !DIExpression()), !dbg !287 + %4 = ptrtoint double** %base.addr to i64 + %5 = load double*, double** %base.addr, align 8, !dbg !288 + %6 = ptrtoint i32* %index.addr to i64 + %7 = load i32, i32* %index.addr, align 4, !dbg !289 + %8 = ptrtoint i32* %index.addr to i64 + %9 = load i32, i32* %index.addr, align 4, !dbg !290 + call void @__dp_call(i32 16390), !dbg !291 + call void @_Z19perform_calculationPdii(double* %5, i32 %7, i32 %9), !dbg !291 + call void @__dp_report_bb(i32 1) + call void @__dp_func_exit(i32 16390, i32 0), !dbg !292 + ret void, !dbg !292 +} + +; Function Attrs: noinline nounwind optnone uwtable +define void @_Z18doall_not_possiblePdii(double* %base, i32 %index, i32 %n) #0 !dbg !293 { +entry: + call void @__dp_func_entry(i32 16392, i32 0) + %base.addr = alloca double*, align 8 + %0 = ptrtoint double** %base.addr to i64 + %index.addr = alloca i32, align 4 + %1 = ptrtoint i32* %index.addr to i64 + %n.addr = alloca i32, align 4 + %2 = ptrtoint i32* %n.addr to i64 + %3 = ptrtoint double** %base.addr to i64 + store double* %base, double** %base.addr, align 8 + call void @llvm.dbg.declare(metadata double** %base.addr, metadata !294, metadata !DIExpression()), !dbg !295 + %4 = ptrtoint i32* %index.addr to i64 + store i32 %index, i32* %index.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %index.addr, metadata !296, metadata !DIExpression()), !dbg !297 + %5 = ptrtoint i32* %n.addr to i64 + store i32 %n, i32* %n.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %n.addr, metadata !298, metadata !DIExpression()), !dbg !299 + %6 = ptrtoint double** %base.addr to i64 + %7 = load double*, double** %base.addr, align 8, !dbg !300 + %8 = ptrtoint i32* %index.addr to i64 + %9 = load i32, i32* %index.addr, align 4, !dbg !301 + %10 = ptrtoint i32* %index.addr to i64 + %11 = load i32, i32* %index.addr, align 4, !dbg !302 + %12 = ptrtoint i32* %n.addr to i64 + %13 = load i32, i32* %n.addr, align 4, !dbg !303 + %rem = srem i32 422, %13, !dbg !304 + %add = add nsw i32 %11, %rem, !dbg !305 + call void @__dp_call(i32 16392), !dbg !306 + call void @_Z19perform_calculationPdii(double* %7, i32 %9, i32 %add), !dbg !306 + call void @__dp_report_bb(i32 2) + call void @__dp_func_exit(i32 16392, i32 0), !dbg !307 + ret void, !dbg !307 +} + +; Function Attrs: noinline norecurse nounwind optnone uwtable +define i32 @main(i32 %argc, i8** %argv) #2 !dbg !2 { +entry: + call void @__dp_func_entry(i32 16394, i32 1) + %__dp_bb16 = alloca i32, align 4 + store i32 0, i32* %__dp_bb16, align 4 + %__dp_bb15 = alloca i32, align 4 + store i32 0, i32* %__dp_bb15, align 4 + %__dp_bb = alloca i32, align 4 + store i32 0, i32* %__dp_bb, align 4 + %retval = alloca i32, align 4 + %0 = ptrtoint i32* %retval to i64 + %argc.addr = alloca i32, align 4 + %1 = ptrtoint i32* %argc.addr to i64 + %argv.addr = alloca i8**, align 8 + %2 = ptrtoint i8*** %argv.addr to i64 + %x = alloca double*, align 8 + %3 = ptrtoint double** %x to i64 + %i = alloca i32, align 4 + %4 = ptrtoint i32* %i to i64 + %i1 = alloca i32, align 4 + %5 = ptrtoint i32* %i1 to i64 + %i8 = alloca i32, align 4 + %6 = ptrtoint i32* %i8 to i64 + %7 = ptrtoint i32* %retval to i64 + store i32 0, i32* %retval, align 4 + %8 = ptrtoint i32* %argc.addr to i64 + store i32 %argc, i32* %argc.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %argc.addr, metadata !308, metadata !DIExpression()), !dbg !309 + %9 = ptrtoint i8*** %argv.addr to i64 + store i8** %argv, i8*** %argv.addr, align 8 + call void @llvm.dbg.declare(metadata i8*** %argv.addr, metadata !310, metadata !DIExpression()), !dbg !311 + call void @llvm.dbg.declare(metadata double** %x, metadata !312, metadata !DIExpression()), !dbg !313 + %10 = ptrtoint i32* @_ZZ4mainE1n to i64 + call void @__dp_read(i32 16397, i64 %10, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.11, i32 0, i32 0)) + %11 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !314 + %conv = sext i32 %11 to i64, !dbg !314 + %mul = mul i64 %conv, 8, !dbg !315 + %call = call noalias i8* @malloc(i64 %mul) #4, !dbg !316 + %12 = ptrtoint i8* %call to i64 + call void @__dp_new(i32 16397, i64 %12, i64 %12, i64 %mul), !dbg !317 + %13 = bitcast i8* %call to double*, !dbg !317 + %14 = ptrtoint double** %x to i64 + store double* %13, double** %x, align 8, !dbg !313 + call void @llvm.dbg.declare(metadata i32* %i, metadata !318, metadata !DIExpression()), !dbg !320 + %15 = ptrtoint i32* %i to i64 + store i32 0, i32* %i, align 4, !dbg !320 + call void @__dp_report_bb(i32 3) + br label %for.cond, !dbg !321 + +for.cond: ; preds = %for.inc, %entry + call void @__dp_loop_entry(i32 16401, i32 0) + %16 = ptrtoint i32* %i to i64 + %17 = load i32, i32* %i, align 4, !dbg !322 + %18 = ptrtoint i32* @_ZZ4mainE1n to i64 + call void @__dp_read(i32 16401, i64 %18, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.11, i32 0, i32 0)) + %19 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !324 + %cmp = icmp slt i32 %17, %19, !dbg !325 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.5, i32 0, i32 0), i1 %cmp, i32 1), !dbg !326 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.6, i32 0, i32 0), i1 %cmp, i32 0), !dbg !326 + call void @__dp_report_bb(i32 4) + %20 = load i32, i32* %__dp_bb, align 4 + call void @__dp_report_bb_pair(i32 %20, i32 16) + br i1 %cmp, label %for.body, label %for.end, !dbg !326 + +for.body: ; preds = %for.cond + call void @__dp_loop_incr(i32 3) + %21 = ptrtoint double** %x to i64 + %22 = load double*, double** %x, align 8, !dbg !327 + %23 = ptrtoint i32* %i to i64 + %24 = load i32, i32* %i, align 4, !dbg !329 + %idxprom = sext i32 %24 to i64, !dbg !327 + %arrayidx = getelementptr inbounds double, double* %22, i64 %idxprom, !dbg !327 + %25 = ptrtoint double* %arrayidx to i64 + call void @__dp_write(i32 16402, i64 %25, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.26, i32 0, i32 0)) + store double 1.000000e+00, double* %arrayidx, align 8, !dbg !330 + call void @__dp_report_bb(i32 7) + %26 = load i32, i32* %__dp_bb, align 4 + call void @__dp_report_bb_pair(i32 %26, i32 18) + br label %for.inc, !dbg !331 + +for.inc: ; preds = %for.body + %27 = ptrtoint i32* %i to i64 + %28 = load i32, i32* %i, align 4, !dbg !332 + %inc = add nsw i32 %28, 1, !dbg !332 + %29 = ptrtoint i32* %i to i64 + store i32 %inc, i32* %i, align 4, !dbg !332 + call void @__dp_report_bb(i32 6) + %30 = load i32, i32* %__dp_bb, align 4 + call void @__dp_report_bb_pair(i32 %30, i32 17) + store i32 1, i32* %__dp_bb, align 4 + br label %for.cond, !dbg !333, !llvm.loop !334 + +for.end: ; preds = %for.cond + call void @__dp_loop_exit(i32 16406, i32 0) + call void @llvm.dbg.declare(metadata i32* %i1, metadata !336, metadata !DIExpression()), !dbg !338 + %31 = ptrtoint i32* %i1 to i64 + store i32 0, i32* %i1, align 4, !dbg !338 + call void @__dp_report_bb(i32 5) + br label %for.cond2, !dbg !339 + +for.cond2: ; preds = %for.inc5, %for.end + call void @__dp_loop_entry(i32 16406, i32 1) + %32 = ptrtoint i32* %i1 to i64 + %33 = load i32, i32* %i1, align 4, !dbg !340 + %34 = ptrtoint i32* @_ZZ4mainE1n to i64 + call void @__dp_read(i32 16406, i64 %34, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.11, i32 0, i32 0)) + %35 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !342 + %cmp3 = icmp slt i32 %33, %35, !dbg !343 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.7, i32 0, i32 0), i1 %cmp3, i32 1), !dbg !344 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.8, i32 0, i32 0), i1 %cmp3, i32 0), !dbg !344 + call void @__dp_report_bb(i32 9) + %36 = load i32, i32* %__dp_bb15, align 4 + call void @__dp_report_bb_pair(i32 %36, i32 19) + br i1 %cmp3, label %for.body4, label %for.end7, !dbg !344 + +for.body4: ; preds = %for.cond2 + call void @__dp_loop_incr(i32 2) + %37 = ptrtoint double** %x to i64 + %38 = load double*, double** %x, align 8, !dbg !345 + %39 = ptrtoint i32* %i1 to i64 + %40 = load i32, i32* %i1, align 4, !dbg !347 + call void @__dp_call(i32 16407), !dbg !348 + call void @_Z14doall_possiblePdi(double* %38, i32 %40), !dbg !348 + call void @__dp_report_bb(i32 11) + %41 = load i32, i32* %__dp_bb15, align 4 + call void @__dp_report_bb_pair(i32 %41, i32 21) + br label %for.inc5, !dbg !349 + +for.inc5: ; preds = %for.body4 + %42 = ptrtoint i32* %i1 to i64 + %43 = load i32, i32* %i1, align 4, !dbg !350 + %inc6 = add nsw i32 %43, 1, !dbg !350 + %44 = ptrtoint i32* %i1 to i64 + store i32 %inc6, i32* %i1, align 4, !dbg !350 + call void @__dp_report_bb(i32 10) + %45 = load i32, i32* %__dp_bb15, align 4 + call void @__dp_report_bb_pair(i32 %45, i32 20) + store i32 1, i32* %__dp_bb15, align 4 + br label %for.cond2, !dbg !351, !llvm.loop !352 + +for.end7: ; preds = %for.cond2 + call void @__dp_loop_exit(i32 16411, i32 1) + call void @llvm.dbg.declare(metadata i32* %i8, metadata !354, metadata !DIExpression()), !dbg !356 + %46 = ptrtoint i32* %i8 to i64 + store i32 0, i32* %i8, align 4, !dbg !356 + call void @__dp_report_bb(i32 8) + br label %for.cond9, !dbg !357 + +for.cond9: ; preds = %for.inc12, %for.end7 + call void @__dp_loop_entry(i32 16411, i32 2) + %47 = ptrtoint i32* %i8 to i64 + %48 = load i32, i32* %i8, align 4, !dbg !358 + %49 = ptrtoint i32* @_ZZ4mainE1n to i64 + call void @__dp_read(i32 16411, i64 %49, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.11, i32 0, i32 0)) + %50 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !360 + %cmp10 = icmp slt i32 %48, %50, !dbg !361 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.9, i32 0, i32 0), i1 %cmp10, i32 1), !dbg !362 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.10, i32 0, i32 0), i1 %cmp10, i32 0), !dbg !362 + call void @__dp_report_bb(i32 13) + %51 = load i32, i32* %__dp_bb16, align 4 + call void @__dp_report_bb_pair(i32 %51, i32 22) + br i1 %cmp10, label %for.body11, label %for.end14, !dbg !362 + +for.body11: ; preds = %for.cond9 + call void @__dp_loop_incr(i32 1) + %52 = ptrtoint double** %x to i64 + %53 = load double*, double** %x, align 8, !dbg !363 + %54 = ptrtoint i32* %i8 to i64 + %55 = load i32, i32* %i8, align 4, !dbg !365 + %56 = ptrtoint i32* @_ZZ4mainE1n to i64 + call void @__dp_read(i32 16412, i64 %56, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.11, i32 0, i32 0)) + %57 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !366 + call void @__dp_call(i32 16412), !dbg !367 + call void @_Z18doall_not_possiblePdii(double* %53, i32 %55, i32 %57), !dbg !367 + call void @__dp_report_bb(i32 15) + %58 = load i32, i32* %__dp_bb16, align 4 + call void @__dp_report_bb_pair(i32 %58, i32 24) + br label %for.inc12, !dbg !368 + +for.inc12: ; preds = %for.body11 + %59 = ptrtoint i32* %i8 to i64 + %60 = load i32, i32* %i8, align 4, !dbg !369 + %inc13 = add nsw i32 %60, 1, !dbg !369 + %61 = ptrtoint i32* %i8 to i64 + store i32 %inc13, i32* %i8, align 4, !dbg !369 + call void @__dp_report_bb(i32 14) + %62 = load i32, i32* %__dp_bb16, align 4 + call void @__dp_report_bb_pair(i32 %62, i32 23) + store i32 1, i32* %__dp_bb16, align 4 + br label %for.cond9, !dbg !370, !llvm.loop !371 + +for.end14: ; preds = %for.cond9 + call void @__dp_loop_exit(i32 16415, i32 2) + %63 = ptrtoint double** %x to i64 + %64 = load double*, double** %x, align 8, !dbg !373 + %65 = bitcast double* %64 to i8*, !dbg !373 + call void @free(i8* %65) #4, !dbg !374 + %66 = ptrtoint i8* %65 to i64 + call void @__dp_delete(i32 16415, i64 %66), !dbg !375 + call void @__dp_report_bb(i32 12) + call void @__dp_finalize(i32 16417), !dbg !375 + call void @__dp_loop_output(), !dbg !375 + call void @__dp_taken_branch_counter_output(), !dbg !375 + ret i32 0, !dbg !375 +} + +; Function Attrs: nounwind +declare noalias i8* @malloc(i64) #3 + +; Function Attrs: nounwind +declare void @free(i8*) #3 + +declare void @__dp_init(i32, i32, i32) + +declare void @__dp_finalize(i32) + +declare void @__dp_read(i32, i64, i8*) + +declare void @__dp_write(i32, i64, i8*) + +declare void @__dp_alloca(i32, i8*, i64, i64, i64, i64) + +declare void @__dp_new(i32, i64, i64, i64) + +declare void @__dp_delete(i32, i64) + +declare void @__dp_call(i32) + +declare void @__dp_func_entry(i32, i32) + +declare void @__dp_func_exit(i32, i32) + +declare void @__dp_loop_entry(i32, i32) + +declare void @__dp_loop_exit(i32, i32) + +declare void @__dp_incr_taken_branch_counter(i8*, i32, i32) + +declare void @__dp_report_bb(i32) + +declare void @__dp_report_bb_pair(i32, i32) + +declare void @__dp_loop_incr(i32) + +declare void @__dp_loop_output() + +declare void @__dp_taken_branch_counter_output() + +attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind readnone speculatable willreturn } +attributes #2 = { noinline norecurse nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #3 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #4 = { nounwind } + +!llvm.dbg.cu = !{!11} +!llvm.module.flags = !{!260, !261, !262, !263} +!llvm.ident = !{!264} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "n", scope: !2, file: !3, line: 11, type: !6, isLocal: true, isDefinition: true) +!2 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 10, type: !4, scopeLine: 10, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !11, retainedNodes: !12) +!3 = !DIFile(filename: "code.cpp", directory: "/home/lukas/git/discopop/test/end_to_end/do_all/calls/complex/src") +!4 = !DISubroutineType(types: !5) +!5 = !{!6, !6, !7} +!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!7 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64) +!8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64) +!9 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !10) +!10 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!11 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 11.1.0 (https://github.com/llvm/llvm-project.git 7e99bddfeaab2713a8bb6ca538da25b66e6efc59)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !12, retainedTypes: !13, globals: !16, imports: !19, splitDebugInlining: false, nameTableKind: None) +!12 = !{} +!13 = !{!14} +!14 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !15, size: 64) +!15 = !DIBasicType(name: "double", size: 64, encoding: DW_ATE_float) +!16 = !{!0, !17} +!17 = !DIGlobalVariableExpression(var: !18, expr: !DIExpression()) +!18 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 12, type: !15, isLocal: true, isDefinition: true) +!19 = !{!20, !27, !31, !38, !42, !47, !49, !53, !57, !61, !75, !79, !83, !87, !91, !96, !100, !104, !108, !112, !120, !124, !128, !130, !134, !138, !143, !149, !153, !157, !159, !167, !171, !179, !181, !185, !189, !193, !197, !202, !207, !212, !213, !214, !215, !217, !218, !219, !220, !221, !222, !223, !225, !226, !227, !228, !229, !230, !231, !236, !237, !238, !239, !240, !241, !242, !243, !244, !245, !246, !247, !248, !249, !250, !251, !252, !253, !254, !255, !256, !257, !258, !259} +!20 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !22, file: !26, line: 52) +!21 = !DINamespace(name: "std", scope: null) +!22 = !DISubprogram(name: "abs", scope: !23, file: !23, line: 848, type: !24, flags: DIFlagPrototyped, spFlags: 0) +!23 = !DIFile(filename: "/usr/include/stdlib.h", directory: "") +!24 = !DISubroutineType(types: !25) +!25 = !{!6, !6} +!26 = !DIFile(filename: "/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/bits/std_abs.h", directory: "") +!27 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !28, file: !30, line: 127) +!28 = !DIDerivedType(tag: DW_TAG_typedef, name: "div_t", file: !23, line: 63, baseType: !29) +!29 = !DICompositeType(tag: DW_TAG_structure_type, file: !23, line: 59, flags: DIFlagFwdDecl, identifier: "_ZTS5div_t") +!30 = !DIFile(filename: "/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/cstdlib", directory: "") +!31 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !32, file: !30, line: 128) +!32 = !DIDerivedType(tag: DW_TAG_typedef, name: "ldiv_t", file: !23, line: 71, baseType: !33) +!33 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !23, line: 67, size: 128, flags: DIFlagTypePassByValue, elements: !34, identifier: "_ZTS6ldiv_t") +!34 = !{!35, !37} +!35 = !DIDerivedType(tag: DW_TAG_member, name: "quot", scope: !33, file: !23, line: 69, baseType: !36, size: 64) +!36 = !DIBasicType(name: "long int", size: 64, encoding: DW_ATE_signed) +!37 = !DIDerivedType(tag: DW_TAG_member, name: "rem", scope: !33, file: !23, line: 70, baseType: !36, size: 64, offset: 64) +!38 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !39, file: !30, line: 130) +!39 = !DISubprogram(name: "abort", scope: !23, file: !23, line: 598, type: !40, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) +!40 = !DISubroutineType(types: !41) +!41 = !{null} +!42 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !43, file: !30, line: 134) +!43 = !DISubprogram(name: "atexit", scope: !23, file: !23, line: 602, type: !44, flags: DIFlagPrototyped, spFlags: 0) +!44 = !DISubroutineType(types: !45) +!45 = !{!6, !46} +!46 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !40, size: 64) +!47 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !48, file: !30, line: 137) +!48 = !DISubprogram(name: "at_quick_exit", scope: !23, file: !23, line: 607, type: !44, flags: DIFlagPrototyped, spFlags: 0) +!49 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !50, file: !30, line: 140) +!50 = !DISubprogram(name: "atof", scope: !23, file: !23, line: 102, type: !51, flags: DIFlagPrototyped, spFlags: 0) +!51 = !DISubroutineType(types: !52) +!52 = !{!15, !8} +!53 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !54, file: !30, line: 141) +!54 = !DISubprogram(name: "atoi", scope: !23, file: !23, line: 105, type: !55, flags: DIFlagPrototyped, spFlags: 0) +!55 = !DISubroutineType(types: !56) +!56 = !{!6, !8} +!57 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !58, file: !30, line: 142) +!58 = !DISubprogram(name: "atol", scope: !23, file: !23, line: 108, type: !59, flags: DIFlagPrototyped, spFlags: 0) +!59 = !DISubroutineType(types: !60) +!60 = !{!36, !8} +!61 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !62, file: !30, line: 143) +!62 = !DISubprogram(name: "bsearch", scope: !23, file: !23, line: 828, type: !63, flags: DIFlagPrototyped, spFlags: 0) +!63 = !DISubroutineType(types: !64) +!64 = !{!65, !66, !66, !68, !68, !71} +!65 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) +!66 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !67, size: 64) +!67 = !DIDerivedType(tag: DW_TAG_const_type, baseType: null) +!68 = !DIDerivedType(tag: DW_TAG_typedef, name: "size_t", file: !69, line: 46, baseType: !70) +!69 = !DIFile(filename: "Software/llvm-11.1.0/lib/clang/11.1.0/include/stddef.h", directory: "/home/lukas") +!70 = !DIBasicType(name: "long unsigned int", size: 64, encoding: DW_ATE_unsigned) +!71 = !DIDerivedType(tag: DW_TAG_typedef, name: "__compar_fn_t", file: !23, line: 816, baseType: !72) +!72 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !73, size: 64) +!73 = !DISubroutineType(types: !74) +!74 = !{!6, !66, !66} +!75 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !76, file: !30, line: 144) +!76 = !DISubprogram(name: "calloc", scope: !23, file: !23, line: 543, type: !77, flags: DIFlagPrototyped, spFlags: 0) +!77 = !DISubroutineType(types: !78) +!78 = !{!65, !68, !68} +!79 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !80, file: !30, line: 145) +!80 = !DISubprogram(name: "div", scope: !23, file: !23, line: 860, type: !81, flags: DIFlagPrototyped, spFlags: 0) +!81 = !DISubroutineType(types: !82) +!82 = !{!28, !6, !6} +!83 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !84, file: !30, line: 146) +!84 = !DISubprogram(name: "exit", scope: !23, file: !23, line: 624, type: !85, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) +!85 = !DISubroutineType(types: !86) +!86 = !{null, !6} +!87 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !88, file: !30, line: 147) +!88 = !DISubprogram(name: "free", scope: !23, file: !23, line: 555, type: !89, flags: DIFlagPrototyped, spFlags: 0) +!89 = !DISubroutineType(types: !90) +!90 = !{null, !65} +!91 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !92, file: !30, line: 148) +!92 = !DISubprogram(name: "getenv", scope: !23, file: !23, line: 641, type: !93, flags: DIFlagPrototyped, spFlags: 0) +!93 = !DISubroutineType(types: !94) +!94 = !{!95, !8} +!95 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64) +!96 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !97, file: !30, line: 149) +!97 = !DISubprogram(name: "labs", scope: !23, file: !23, line: 849, type: !98, flags: DIFlagPrototyped, spFlags: 0) +!98 = !DISubroutineType(types: !99) +!99 = !{!36, !36} +!100 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !101, file: !30, line: 150) +!101 = !DISubprogram(name: "ldiv", scope: !23, file: !23, line: 862, type: !102, flags: DIFlagPrototyped, spFlags: 0) +!102 = !DISubroutineType(types: !103) +!103 = !{!32, !36, !36} +!104 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !105, file: !30, line: 151) +!105 = !DISubprogram(name: "malloc", scope: !23, file: !23, line: 540, type: !106, flags: DIFlagPrototyped, spFlags: 0) +!106 = !DISubroutineType(types: !107) +!107 = !{!65, !68} +!108 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !109, file: !30, line: 153) +!109 = !DISubprogram(name: "mblen", scope: !23, file: !23, line: 930, type: !110, flags: DIFlagPrototyped, spFlags: 0) +!110 = !DISubroutineType(types: !111) +!111 = !{!6, !8, !68} +!112 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !113, file: !30, line: 154) +!113 = !DISubprogram(name: "mbstowcs", scope: !23, file: !23, line: 941, type: !114, flags: DIFlagPrototyped, spFlags: 0) +!114 = !DISubroutineType(types: !115) +!115 = !{!68, !116, !119, !68} +!116 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !117) +!117 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !118, size: 64) +!118 = !DIBasicType(name: "wchar_t", size: 32, encoding: DW_ATE_signed) +!119 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !8) +!120 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !121, file: !30, line: 155) +!121 = !DISubprogram(name: "mbtowc", scope: !23, file: !23, line: 933, type: !122, flags: DIFlagPrototyped, spFlags: 0) +!122 = !DISubroutineType(types: !123) +!123 = !{!6, !116, !119, !68} +!124 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !125, file: !30, line: 157) +!125 = !DISubprogram(name: "qsort", scope: !23, file: !23, line: 838, type: !126, flags: DIFlagPrototyped, spFlags: 0) +!126 = !DISubroutineType(types: !127) +!127 = !{null, !65, !68, !68, !71} +!128 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !129, file: !30, line: 160) +!129 = !DISubprogram(name: "quick_exit", scope: !23, file: !23, line: 630, type: !85, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) +!130 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !131, file: !30, line: 163) +!131 = !DISubprogram(name: "rand", scope: !23, file: !23, line: 454, type: !132, flags: DIFlagPrototyped, spFlags: 0) +!132 = !DISubroutineType(types: !133) +!133 = !{!6} +!134 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !135, file: !30, line: 164) +!135 = !DISubprogram(name: "realloc", scope: !23, file: !23, line: 551, type: !136, flags: DIFlagPrototyped, spFlags: 0) +!136 = !DISubroutineType(types: !137) +!137 = !{!65, !65, !68} +!138 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !139, file: !30, line: 165) +!139 = !DISubprogram(name: "srand", scope: !23, file: !23, line: 456, type: !140, flags: DIFlagPrototyped, spFlags: 0) +!140 = !DISubroutineType(types: !141) +!141 = !{null, !142} +!142 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned) +!143 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !144, file: !30, line: 166) +!144 = !DISubprogram(name: "strtod", scope: !23, file: !23, line: 118, type: !145, flags: DIFlagPrototyped, spFlags: 0) +!145 = !DISubroutineType(types: !146) +!146 = !{!15, !119, !147} +!147 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !148) +!148 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !95, size: 64) +!149 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !150, file: !30, line: 167) +!150 = !DISubprogram(name: "strtol", scope: !23, file: !23, line: 177, type: !151, flags: DIFlagPrototyped, spFlags: 0) +!151 = !DISubroutineType(types: !152) +!152 = !{!36, !119, !147, !6} +!153 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !154, file: !30, line: 168) +!154 = !DISubprogram(name: "strtoul", scope: !23, file: !23, line: 181, type: !155, flags: DIFlagPrototyped, spFlags: 0) +!155 = !DISubroutineType(types: !156) +!156 = !{!70, !119, !147, !6} +!157 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !158, file: !30, line: 169) +!158 = !DISubprogram(name: "system", scope: !23, file: !23, line: 791, type: !55, flags: DIFlagPrototyped, spFlags: 0) +!159 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !160, file: !30, line: 171) +!160 = !DISubprogram(name: "wcstombs", scope: !23, file: !23, line: 945, type: !161, flags: DIFlagPrototyped, spFlags: 0) +!161 = !DISubroutineType(types: !162) +!162 = !{!68, !163, !164, !68} +!163 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !95) +!164 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !165) +!165 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !166, size: 64) +!166 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !118) +!167 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !168, file: !30, line: 172) +!168 = !DISubprogram(name: "wctomb", scope: !23, file: !23, line: 937, type: !169, flags: DIFlagPrototyped, spFlags: 0) +!169 = !DISubroutineType(types: !170) +!170 = !{!6, !95, !118} +!171 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !172, entity: !173, file: !30, line: 200) +!172 = !DINamespace(name: "__gnu_cxx", scope: null) +!173 = !DIDerivedType(tag: DW_TAG_typedef, name: "lldiv_t", file: !23, line: 81, baseType: !174) +!174 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !23, line: 77, size: 128, flags: DIFlagTypePassByValue, elements: !175, identifier: "_ZTS7lldiv_t") +!175 = !{!176, !178} +!176 = !DIDerivedType(tag: DW_TAG_member, name: "quot", scope: !174, file: !23, line: 79, baseType: !177, size: 64) +!177 = !DIBasicType(name: "long long int", size: 64, encoding: DW_ATE_signed) +!178 = !DIDerivedType(tag: DW_TAG_member, name: "rem", scope: !174, file: !23, line: 80, baseType: !177, size: 64, offset: 64) +!179 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !172, entity: !180, file: !30, line: 206) +!180 = !DISubprogram(name: "_Exit", scope: !23, file: !23, line: 636, type: !85, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) +!181 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !172, entity: !182, file: !30, line: 210) +!182 = !DISubprogram(name: "llabs", scope: !23, file: !23, line: 852, type: !183, flags: DIFlagPrototyped, spFlags: 0) +!183 = !DISubroutineType(types: !184) +!184 = !{!177, !177} +!185 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !172, entity: !186, file: !30, line: 216) +!186 = !DISubprogram(name: "lldiv", scope: !23, file: !23, line: 866, type: !187, flags: DIFlagPrototyped, spFlags: 0) +!187 = !DISubroutineType(types: !188) +!188 = !{!173, !177, !177} +!189 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !172, entity: !190, file: !30, line: 227) +!190 = !DISubprogram(name: "atoll", scope: !23, file: !23, line: 113, type: !191, flags: DIFlagPrototyped, spFlags: 0) +!191 = !DISubroutineType(types: !192) +!192 = !{!177, !8} +!193 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !172, entity: !194, file: !30, line: 228) +!194 = !DISubprogram(name: "strtoll", scope: !23, file: !23, line: 201, type: !195, flags: DIFlagPrototyped, spFlags: 0) +!195 = !DISubroutineType(types: !196) +!196 = !{!177, !119, !147, !6} +!197 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !172, entity: !198, file: !30, line: 229) +!198 = !DISubprogram(name: "strtoull", scope: !23, file: !23, line: 206, type: !199, flags: DIFlagPrototyped, spFlags: 0) +!199 = !DISubroutineType(types: !200) +!200 = !{!201, !119, !147, !6} +!201 = !DIBasicType(name: "long long unsigned int", size: 64, encoding: DW_ATE_unsigned) +!202 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !172, entity: !203, file: !30, line: 231) +!203 = !DISubprogram(name: "strtof", scope: !23, file: !23, line: 124, type: !204, flags: DIFlagPrototyped, spFlags: 0) +!204 = !DISubroutineType(types: !205) +!205 = !{!206, !119, !147} +!206 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) +!207 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !172, entity: !208, file: !30, line: 232) +!208 = !DISubprogram(name: "strtold", scope: !23, file: !23, line: 127, type: !209, flags: DIFlagPrototyped, spFlags: 0) +!209 = !DISubroutineType(types: !210) +!210 = !{!211, !119, !147} +!211 = !DIBasicType(name: "long double", size: 128, encoding: DW_ATE_float) +!212 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !173, file: !30, line: 240) +!213 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !180, file: !30, line: 242) +!214 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !182, file: !30, line: 244) +!215 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !216, file: !30, line: 245) +!216 = !DISubprogram(name: "div", linkageName: "_ZN9__gnu_cxx3divExx", scope: !172, file: !30, line: 213, type: !187, flags: DIFlagPrototyped, spFlags: 0) +!217 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !186, file: !30, line: 246) +!218 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !190, file: !30, line: 248) +!219 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !203, file: !30, line: 249) +!220 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !194, file: !30, line: 250) +!221 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !198, file: !30, line: 251) +!222 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !208, file: !30, line: 252) +!223 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !39, file: !224, line: 38) +!224 = !DIFile(filename: "/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/stdlib.h", directory: "") +!225 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !43, file: !224, line: 39) +!226 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !84, file: !224, line: 40) +!227 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !48, file: !224, line: 43) +!228 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !129, file: !224, line: 46) +!229 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !28, file: !224, line: 51) +!230 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !32, file: !224, line: 52) +!231 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !232, file: !224, line: 54) +!232 = !DISubprogram(name: "abs", linkageName: "_ZSt3absg", scope: !21, file: !26, line: 103, type: !233, flags: DIFlagPrototyped, spFlags: 0) +!233 = !DISubroutineType(types: !234) +!234 = !{!235, !235} +!235 = !DIBasicType(name: "__float128", size: 128, encoding: DW_ATE_float) +!236 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !50, file: !224, line: 55) +!237 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !54, file: !224, line: 56) +!238 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !58, file: !224, line: 57) +!239 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !62, file: !224, line: 58) +!240 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !76, file: !224, line: 59) +!241 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !216, file: !224, line: 60) +!242 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !88, file: !224, line: 61) +!243 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !92, file: !224, line: 62) +!244 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !97, file: !224, line: 63) +!245 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !101, file: !224, line: 64) +!246 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !105, file: !224, line: 65) +!247 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !109, file: !224, line: 67) +!248 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !113, file: !224, line: 68) +!249 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !121, file: !224, line: 69) +!250 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !125, file: !224, line: 71) +!251 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !131, file: !224, line: 72) +!252 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !135, file: !224, line: 73) +!253 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !139, file: !224, line: 74) +!254 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !144, file: !224, line: 75) +!255 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !150, file: !224, line: 76) +!256 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !154, file: !224, line: 77) +!257 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !158, file: !224, line: 78) +!258 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !160, file: !224, line: 80) +!259 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !168, file: !224, line: 81) +!260 = !{i32 7, !"Dwarf Version", i32 4} +!261 = !{i32 2, !"Debug Info Version", i32 3} +!262 = !{i32 1, !"wchar_size", i32 4} +!263 = !{i32 7, !"PIC Level", i32 2} +!264 = !{!"clang version 11.1.0 (https://github.com/llvm/llvm-project.git 7e99bddfeaab2713a8bb6ca538da25b66e6efc59)"} +!265 = distinct !DISubprogram(name: "perform_calculation", linkageName: "_Z19perform_calculationPdii", scope: !3, file: !3, line: 4, type: !266, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !11, retainedNodes: !12) +!266 = !DISubroutineType(types: !267) +!267 = !{null, !14, !6, !6} +!268 = !DILocalVariable(name: "base", arg: 1, scope: !265, file: !3, line: 4, type: !14) +!269 = !DILocation(line: 4, column: 34, scope: !265) +!270 = !DILocalVariable(name: "offset_1", arg: 2, scope: !265, file: !3, line: 4, type: !6) +!271 = !DILocation(line: 4, column: 44, scope: !265) +!272 = !DILocalVariable(name: "offset_2", arg: 3, scope: !265, file: !3, line: 4, type: !6) +!273 = !DILocation(line: 4, column: 58, scope: !265) +!274 = !DILocation(line: 4, column: 92, scope: !265) +!275 = !DILocation(line: 4, column: 97, scope: !265) +!276 = !DILocation(line: 4, column: 90, scope: !265) +!277 = !DILocation(line: 4, column: 70, scope: !265) +!278 = !DILocation(line: 4, column: 75, scope: !265) +!279 = !DILocation(line: 4, column: 85, scope: !265) +!280 = !DILocation(line: 4, column: 108, scope: !265) +!281 = distinct !DISubprogram(name: "doall_possible", linkageName: "_Z14doall_possiblePdi", scope: !3, file: !3, line: 6, type: !282, scopeLine: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !11, retainedNodes: !12) +!282 = !DISubroutineType(types: !283) +!283 = !{null, !14, !6} +!284 = !DILocalVariable(name: "base", arg: 1, scope: !281, file: !3, line: 6, type: !14) +!285 = !DILocation(line: 6, column: 29, scope: !281) +!286 = !DILocalVariable(name: "index", arg: 2, scope: !281, file: !3, line: 6, type: !6) +!287 = !DILocation(line: 6, column: 39, scope: !281) +!288 = !DILocation(line: 6, column: 68, scope: !281) +!289 = !DILocation(line: 6, column: 74, scope: !281) +!290 = !DILocation(line: 6, column: 81, scope: !281) +!291 = !DILocation(line: 6, column: 48, scope: !281) +!292 = !DILocation(line: 6, column: 89, scope: !281) +!293 = distinct !DISubprogram(name: "doall_not_possible", linkageName: "_Z18doall_not_possiblePdii", scope: !3, file: !3, line: 8, type: !266, scopeLine: 8, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !11, retainedNodes: !12) +!294 = !DILocalVariable(name: "base", arg: 1, scope: !293, file: !3, line: 8, type: !14) +!295 = !DILocation(line: 8, column: 33, scope: !293) +!296 = !DILocalVariable(name: "index", arg: 2, scope: !293, file: !3, line: 8, type: !6) +!297 = !DILocation(line: 8, column: 43, scope: !293) +!298 = !DILocalVariable(name: "n", arg: 3, scope: !293, file: !3, line: 8, type: !6) +!299 = !DILocation(line: 8, column: 54, scope: !293) +!300 = !DILocation(line: 8, column: 79, scope: !293) +!301 = !DILocation(line: 8, column: 85, scope: !293) +!302 = !DILocation(line: 8, column: 93, scope: !293) +!303 = !DILocation(line: 8, column: 107, scope: !293) +!304 = !DILocation(line: 8, column: 105, scope: !293) +!305 = !DILocation(line: 8, column: 99, scope: !293) +!306 = !DILocation(line: 8, column: 59, scope: !293) +!307 = !DILocation(line: 8, column: 112, scope: !293) +!308 = !DILocalVariable(name: "argc", arg: 1, scope: !2, file: !3, line: 10, type: !6) +!309 = !DILocation(line: 10, column: 14, scope: !2) +!310 = !DILocalVariable(name: "argv", arg: 2, scope: !2, file: !3, line: 10, type: !7) +!311 = !DILocation(line: 10, column: 32, scope: !2) +!312 = !DILocalVariable(name: "x", scope: !2, file: !3, line: 13, type: !14) +!313 = !DILocation(line: 13, column: 11, scope: !2) +!314 = !DILocation(line: 13, column: 32, scope: !2) +!315 = !DILocation(line: 13, column: 34, scope: !2) +!316 = !DILocation(line: 13, column: 25, scope: !2) +!317 = !DILocation(line: 13, column: 15, scope: !2) +!318 = !DILocalVariable(name: "i", scope: !319, file: !3, line: 17, type: !6) +!319 = distinct !DILexicalBlock(scope: !2, file: !3, line: 17, column: 3) +!320 = !DILocation(line: 17, column: 12, scope: !319) +!321 = !DILocation(line: 17, column: 8, scope: !319) +!322 = !DILocation(line: 17, column: 19, scope: !323) +!323 = distinct !DILexicalBlock(scope: !319, file: !3, line: 17, column: 3) +!324 = !DILocation(line: 17, column: 23, scope: !323) +!325 = !DILocation(line: 17, column: 21, scope: !323) +!326 = !DILocation(line: 17, column: 3, scope: !319) +!327 = !DILocation(line: 18, column: 5, scope: !328) +!328 = distinct !DILexicalBlock(scope: !323, file: !3, line: 17, column: 31) +!329 = !DILocation(line: 18, column: 7, scope: !328) +!330 = !DILocation(line: 18, column: 10, scope: !328) +!331 = !DILocation(line: 19, column: 3, scope: !328) +!332 = !DILocation(line: 17, column: 26, scope: !323) +!333 = !DILocation(line: 17, column: 3, scope: !323) +!334 = distinct !{!334, !326, !335} +!335 = !DILocation(line: 19, column: 3, scope: !319) +!336 = !DILocalVariable(name: "i", scope: !337, file: !3, line: 22, type: !6) +!337 = distinct !DILexicalBlock(scope: !2, file: !3, line: 22, column: 3) +!338 = !DILocation(line: 22, column: 12, scope: !337) +!339 = !DILocation(line: 22, column: 8, scope: !337) +!340 = !DILocation(line: 22, column: 19, scope: !341) +!341 = distinct !DILexicalBlock(scope: !337, file: !3, line: 22, column: 3) +!342 = !DILocation(line: 22, column: 23, scope: !341) +!343 = !DILocation(line: 22, column: 21, scope: !341) +!344 = !DILocation(line: 22, column: 3, scope: !337) +!345 = !DILocation(line: 23, column: 20, scope: !346) +!346 = distinct !DILexicalBlock(scope: !341, file: !3, line: 22, column: 31) +!347 = !DILocation(line: 23, column: 23, scope: !346) +!348 = !DILocation(line: 23, column: 5, scope: !346) +!349 = !DILocation(line: 24, column: 3, scope: !346) +!350 = !DILocation(line: 22, column: 27, scope: !341) +!351 = !DILocation(line: 22, column: 3, scope: !341) +!352 = distinct !{!352, !344, !353} +!353 = !DILocation(line: 24, column: 3, scope: !337) +!354 = !DILocalVariable(name: "i", scope: !355, file: !3, line: 27, type: !6) +!355 = distinct !DILexicalBlock(scope: !2, file: !3, line: 27, column: 3) +!356 = !DILocation(line: 27, column: 12, scope: !355) +!357 = !DILocation(line: 27, column: 8, scope: !355) +!358 = !DILocation(line: 27, column: 19, scope: !359) +!359 = distinct !DILexicalBlock(scope: !355, file: !3, line: 27, column: 3) +!360 = !DILocation(line: 27, column: 23, scope: !359) +!361 = !DILocation(line: 27, column: 21, scope: !359) +!362 = !DILocation(line: 27, column: 3, scope: !355) +!363 = !DILocation(line: 28, column: 24, scope: !364) +!364 = distinct !DILexicalBlock(scope: !359, file: !3, line: 27, column: 31) +!365 = !DILocation(line: 28, column: 27, scope: !364) +!366 = !DILocation(line: 28, column: 30, scope: !364) +!367 = !DILocation(line: 28, column: 5, scope: !364) +!368 = !DILocation(line: 29, column: 3, scope: !364) +!369 = !DILocation(line: 27, column: 27, scope: !359) +!370 = !DILocation(line: 27, column: 3, scope: !359) +!371 = distinct !{!371, !362, !372} +!372 = !DILocation(line: 29, column: 3, scope: !355) +!373 = !DILocation(line: 31, column: 8, scope: !2) +!374 = !DILocation(line: 31, column: 3, scope: !2) +!375 = !DILocation(line: 33, column: 3, scope: !2) From b9d588f15d7b4906530502ba917c987bb9813a83 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Thu, 11 Jul 2024 16:46:15 +0200 Subject: [PATCH 021/105] mypy: add --disallow-untyped-defs --- mypy.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy.ini b/mypy.ini index 728aa51a1..bf4b91e39 100644 --- a/mypy.ini +++ b/mypy.ini @@ -31,10 +31,10 @@ strict_equality = True disallow_any_generics = True check_untyped_defs = True disallow_incomplete_defs = True +disallow_untyped_defs = True # the following options should be enabled one by one, then we will switch to `strict` type checking: #disallow_untyped_calls = True -#disallow_untyped_defs = True #warn_unused_ignores = True #extra-checks (command line flag of mypy... is there a way to set it in the config file?) #strict = True From b3f79bf08058a22330f35af504412785ee949246 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Fri, 12 Jul 2024 12:58:56 +0200 Subject: [PATCH 022/105] chore(mypy): add type annotations --- discopop_explorer/PEGraphX.py | 28 +- discopop_explorer/__main__.py | 2 +- discopop_explorer/discopop_explorer.py | 6 +- discopop_explorer/generate_Data_CUInst.py | 2 +- discopop_explorer/json_serializer.py | 4 +- discopop_explorer/parallel_utils.py | 8 +- discopop_explorer/parser.py | 27 +- discopop_explorer/pattern_detection.py | 37 +- .../pattern_detectors/PatternBase.py | 2 +- .../CombinedGPURegions.py | 12 +- .../classes/Dependency.py | 2 +- .../classes/EntryPoint.py | 12 +- .../classes/ExitPoint.py | 13 +- .../combined_gpu_patterns/classes/Update.py | 11 +- .../combined_gpu_patterns/step_4.py | 4 +- .../combined_gpu_patterns/step_6.py | 52 +- .../pattern_detectors/device_updates.py | 2 +- .../pattern_detectors/do_all_detector.py | 6 +- .../geometric_decomposition_detector.py | 11 +- .../pattern_detectors/pipeline_detector.py | 8 +- .../pattern_detectors/reduction_detector.py | 8 +- .../simple_gpu_patterns/GPULoop.py | 8 +- .../simple_gpu_patterns/GPURegions.py | 4 +- .../task_parallelism/classes.py | 6 +- .../task_parallelism/preprocessor.py | 16 +- .../task_parallelism_detector.py | 2 +- .../task_parallelism/tp_utils.py | 8 +- discopop_explorer/plugins/pipeline.py | 14 +- discopop_explorer/utils.py | 8 +- discopop_explorer/variable.py | 13 +- .../CodeGenerator/CodeGeneratorArguments.py | 6 +- .../CodeGenerator/classes/Pragma.py | 2 +- .../classes/UnpackedSuggestion.py | 4 +- .../ConfigProvider/ConfigProviderArguments.py | 6 +- .../DependencyMetadata/compare_metadata.py | 2 +- .../HostpotLoader/HotspotLoaderArguments.py | 6 +- .../PatchApplicatorArguments.py | 4 +- .../PatchGenerator/PatchGeneratorArguments.py | 4 +- discopop_library/PatchGenerator/__main__.py | 2 +- .../CostModels/CostModel.py | 34 +- .../DataTransfers/NewDataTransfers.py | 6 +- .../DelaunayInterpolatedMicrobench.py | 10 +- .../ExtrapInterpolatedMicrobench.py | 11 +- .../Microbench/PureDataMicrobench.py | 14 +- .../discopop_optimizer/OptimizationGraph.py | 2 +- .../discopop_optimizer/OptimizerArguments.py | 4 +- .../discopop_optimizer/PETParser/PETParser.py | 50 +- .../RemoveDuplicatedUpdates.py | 6 +- .../Variables/Experiment.py | 2 +- .../Variables/ExperimentUtils.py | 2 +- .../discopop_optimizer/__main__.py | 2 +- .../classes/context/ContextObject.py | 2 +- .../classes/context/Update.py | 2 +- .../classes/nodes/GenericNode.py | 2 +- .../discopop_optimizer/classes/nodes/Loop.py | 2 +- .../classes/nodes/Workload.py | 2 +- .../classes/system/Network.py | 2 +- .../classes/types/DataAccessType.py | 10 +- .../gui/presentation/OptionTable.py | 2 +- .../gui/queries/ValueTableQuery.py | 2 +- .../gui/widgets/ScrollableFrame.py | 5 +- .../optimization/evolutionary_algorithm.py | 4 +- .../discopop_optimizer/optimization/greedy.py | 2 +- .../scheduling/workload_delta.py | 12 +- .../suggestions/optimizers/loop_collapse.py | 4 +- .../utilities/MOGUtilities.py | 8 +- .../utilities/visualization/plotting.py | 6 +- .../utilities/visualization/update_graph.py | 4 +- .../result_classes/DetectionResult.py | 8 +- .../result_classes/PatternStorage.py | 2 +- .../src/FileMapping.txt | 1 + .../above_nesting_level_3/src/FileMapping.txt | 1 + .../calls/above_nesting_level_3/src/code.ll | 855 ++++++++++++++++++ .../do_all/calls/allowing/src/FileMapping.txt | 1 + .../do_all/calls/allowing/src/code.ll | 552 +++++++++++ .../do_all/calls/complex/src/FileMapping.txt | 1 - .../do_all/calls/complex/src/code.ll | 780 ---------------- .../positive/simple_1/src/FileMapping.txt | 1 + .../negative/case_1/src/FileMapping.txt | 1 + .../negative/case_1/src/code.ll | 427 +++++++++ .../OMPSCR/c_Mandelbrot/src/FileMapping.txt | 1 + .../command_execution_wrapper.py | 4 +- 82 files changed, 2185 insertions(+), 1036 deletions(-) create mode 100644 test/end_to_end/do_all/backwards_array_access/src/FileMapping.txt create mode 100644 test/end_to_end/do_all/calls/above_nesting_level_3/src/FileMapping.txt create mode 100644 test/end_to_end/do_all/calls/above_nesting_level_3/src/code.ll create mode 100644 test/end_to_end/do_all/calls/allowing/src/FileMapping.txt create mode 100644 test/end_to_end/do_all/calls/allowing/src/code.ll delete mode 100644 test/end_to_end/do_all/calls/complex/src/FileMapping.txt delete mode 100644 test/end_to_end/do_all/calls/complex/src/code.ll create mode 100644 test/end_to_end/optimizer/loop_collapse/positive/simple_1/src/FileMapping.txt create mode 100644 test/end_to_end/reduction_pattern/negative/case_1/src/FileMapping.txt create mode 100644 test/end_to_end/reduction_pattern/negative/case_1/src/code.ll create mode 100644 test/end_to_end/reduction_pattern/positive/nested/OMPSCR/c_Mandelbrot/src/FileMapping.txt diff --git a/discopop_explorer/PEGraphX.py b/discopop_explorer/PEGraphX.py index 569250686..4129b03ee 100644 --- a/discopop_explorer/PEGraphX.py +++ b/discopop_explorer/PEGraphX.py @@ -159,7 +159,7 @@ def __init__(self, type: EdgeType): self.metadata_sink_ancestors = [] self.metadata_source_ancestors = [] - def __str__(self): + def __str__(self) -> str: return self.var_name if self.var_name is not None else str(self.etype) @@ -233,13 +233,13 @@ def contains_line(self, other_line: str) -> bool: return True return False - def __str__(self): + def __str__(self) -> str: return self.id - def __eq__(self, other): + def __eq__(self, other: Any) -> bool: return isinstance(other, Node) and other.file_id == self.file_id and other.node_id == self.node_id - def __hash__(self): + def __hash__(self) -> int: return hash(self.id) def get_parent_id(self, pet: PEGraphX) -> Optional[NodeID]: @@ -722,7 +722,7 @@ def from_parsed_input( print("\tAdded dependencies...") return cls(g, reduction_vars, pos) - def map_static_and_dynamic_dependencies(self): + def map_static_and_dynamic_dependencies(self) -> None: print("\tMapping static to dynamic dependencies...") print("\t\tIdentifying mappings between static and dynamic memory regions...", end=" ") mem_reg_mappings: Dict[MemoryRegion, Set[MemoryRegion]] = dict() @@ -883,7 +883,7 @@ def calculateFunctionMetadata( self.g.remove_edge(edge[0], edge[1], edge[2]) print("Cleaning dependencies II done.") - def calculateLoopMetadata(self): + def calculateLoopMetadata(self) -> None: print("Calculating loop metadata") # calculate loop indices @@ -905,7 +905,7 @@ def calculateLoopMetadata(self): print("Calculating loop metadata done.") - def show(self): + def show(self) -> None: """Plots the graph :return: @@ -1011,7 +1011,7 @@ def all_nodes(self) -> List[Node]: ... @overload def all_nodes(self, type: Union[Type[NodeT], Tuple[Type[NodeT], ...]]) -> List[NodeT]: ... - def all_nodes(self, type=Node): + def all_nodes(self, type: Any = Node) -> List[NodeT]: """List of all nodes of specified type :param type: type(s) of nodes @@ -1057,7 +1057,7 @@ def subtree_of_type(self, root: Node) -> List[Node]: ... @overload def subtree_of_type(self, root: Node, type: Union[Type[NodeT], Tuple[Type[NodeT], ...]]) -> List[NodeT]: ... - def subtree_of_type(self, root, type=Node): + def subtree_of_type(self, root: Node, type: Any = Node) -> List[NodeT]: """Gets all nodes in subtree of specified type including root :param root: root node @@ -1074,7 +1074,7 @@ def subtree_of_type_rec( self, root: Node, visited: Set[Node], type: Union[Type[NodeT], Tuple[Type[NodeT], ...]] ) -> List[NodeT]: ... - def subtree_of_type_rec(self, root, visited, type=Node): + def subtree_of_type_rec(self, root: Node, visited: Set[Node], type: Any = Node) -> List[NodeT]: """recursive helper function for subtree_of_type""" # check if root is of type target res = [] @@ -1286,7 +1286,7 @@ def is_scalar_val(self, allVars: List[Variable], var: str) -> bool: """ for x in allVars: if x.name == var: - return not (x.type.endswith("**") or x.type.startswith("ARRAY" or x.type.startswith("["))) + return not (x.type.endswith("**") or x.type.startswith("ARRAY") or x.type.startswith("[")) else: return False raise ValueError("allVars must not be empty.") @@ -1557,14 +1557,14 @@ def get_reduction_sign(self, line: str, name: str) -> str: return rv["operation"] return "" - def dump_to_pickled_json(self): + def dump_to_pickled_json(self) -> str: """Encodes and returns the entire Object into a pickled json string. The encoded string can be reconstructed into an object by using: jsonpickle.decode(json_str) :return: encoded string """ - return jsonpickle.encode(self) + return cast(str, jsonpickle.encode(self)) def check_reachability(self, target: Node, source: Node, edge_types: List[EdgeType]) -> bool: """check if target is reachable from source via edges of types edge_type. @@ -1667,7 +1667,7 @@ def check_reachability_and_get_path_nodes( queue.append((cast(CUNode, self.node_at(e[0])), tmp_path)) return False, [] - def dump_to_gephi_file(self, name="pet.gexf"): + def dump_to_gephi_file(self, name: str = "pet.gexf") -> None: """Note: Destroys the PETGraph!""" # replace node data with label for node_id in self.g.nodes: diff --git a/discopop_explorer/__main__.py b/discopop_explorer/__main__.py index 07c5141e5..7ae3388c9 100644 --- a/discopop_explorer/__main__.py +++ b/discopop_explorer/__main__.py @@ -159,7 +159,7 @@ def parse_args() -> ExplorerArguments: ) -def main(): +def main() -> None: arguments = parse_args() setup_logger(arguments) run(arguments) diff --git a/discopop_explorer/discopop_explorer.py b/discopop_explorer/discopop_explorer.py index 69c4c390b..ee6cdf332 100644 --- a/discopop_explorer/discopop_explorer.py +++ b/discopop_explorer/discopop_explorer.py @@ -65,10 +65,10 @@ class ExplorerArguments(GeneralArguments): microbench_file: Optional[str] load_existing_doall_and_reduction_patterns: bool - def __post_init__(self): + def __post_init__(self) -> None: self.__validate() - def __validate(self): + def __validate(self) -> None: """Validate the arguments passed to the discopop_explorer, e.g check if given files exist""" validation_failure = False @@ -114,7 +114,7 @@ def __run( hotspot_functions: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]]] = None, load_existing_doall_and_reduction_patterns: bool = False, ) -> DetectionResult: - pet = PEGraphX.from_parsed_input(*parse_inputs(cu_xml, dep_file, reduction_file, file_mapping)) + pet = PEGraphX.from_parsed_input(*parse_inputs(cu_xml, dep_file, reduction_file, file_mapping)) # type: ignore print("PET CREATION FINISHED.") # pet.show() # TODO add visualization diff --git a/discopop_explorer/generate_Data_CUInst.py b/discopop_explorer/generate_Data_CUInst.py index 402138250..cb211aa27 100644 --- a/discopop_explorer/generate_Data_CUInst.py +++ b/discopop_explorer/generate_Data_CUInst.py @@ -179,7 +179,7 @@ def cu_instantiation_input_cpp(pet: PEGraphX, output_file: str) -> None: def wrapper(cu_xml: str, dep_file: str, loop_counter_file: str, reduction_file: str, output_file: str) -> None: """Wrapper to generate the Data_CUInst.txt file, required for the generation of CUInstResult.txt""" # 1. generate PET Graph - pet = PEGraphX.from_parsed_input(*parse_inputs(cu_xml, dep_file, loop_counter_file, reduction_file)) + pet = PEGraphX.from_parsed_input(*parse_inputs(cu_xml, dep_file, loop_counter_file, reduction_file)) # type: ignore # 2. Generate Data_CUInst.txt cu_instantiation_input_cpp(pet, output_file) diff --git a/discopop_explorer/json_serializer.py b/discopop_explorer/json_serializer.py index fdb868e16..1281f36f0 100644 --- a/discopop_explorer/json_serializer.py +++ b/discopop_explorer/json_serializer.py @@ -7,7 +7,7 @@ # directory for details. from json import JSONEncoder -from typing import Dict, Any +from typing import Dict, Any, List from discopop_explorer.pattern_detectors.PatternBase import PatternBase from discopop_library.discopop_optimizer.classes.context.Update import Update from discopop_library.discopop_optimizer.classes.types.DataAccessType import WriteDataAccess @@ -37,7 +37,7 @@ def filter_members(d: Dict[Any, Any]) -> Dict[Any, Any]: class PatternBaseSerializer(JSONEncoder): """Json Encoder for Pattern Info""" - def default(self, o): + def default(self, o: Any) -> Any: try: iterable = iter(o) except TypeError: diff --git a/discopop_explorer/parallel_utils.py b/discopop_explorer/parallel_utils.py index 79ae448e0..818e51b9d 100644 --- a/discopop_explorer/parallel_utils.py +++ b/discopop_explorer/parallel_utils.py @@ -6,18 +6,18 @@ # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. -from .PEGraphX import Node, NodeID, PEGraphX -from typing import List, Optional, Set +from .PEGraphX import FunctionNode, Node, NodeID, PEGraphX +from typing import Any, List, Optional, Set, Tuple global_pet: Optional[PEGraphX] = None -def pet_function_metadata_initialize_worker(pet): +def pet_function_metadata_initialize_worker(pet: PEGraphX) -> None: global global_pet global_pet = pet -def pet_function_metadata_parse_func(func_node): +def pet_function_metadata_parse_func(func_node: FunctionNode) -> Tuple[NodeID, Any, set[NodeID]]: if global_pet is None: raise ValueError("global_pet is None!") diff --git a/discopop_explorer/parser.py b/discopop_explorer/parser.py index 3ab39fcb6..22d46c6e8 100644 --- a/discopop_explorer/parser.py +++ b/discopop_explorer/parser.py @@ -13,9 +13,10 @@ from collections import defaultdict from dataclasses import dataclass from os.path import abspath, dirname -from typing import Any, Dict, List, Tuple +from typing import Any, Dict, List, Optional, Tuple from lxml import objectify # type:ignore +from lxml.objectify import ObjectifiedElement # type: ignore # Map to record which line belongs to read set of nodes. LID -> NodeIds readlineToCUIdMap = defaultdict(set) # type: ignore @@ -46,7 +47,7 @@ class LoopData(object): maximum_iteration_count: int -def __parse_xml_input(xml_fd): +def __parse_xml_input(xml_fd: TextIOWrapper) -> Dict[str, ObjectifiedElement]: xml_content = "" for line in xml_fd.readlines(): if not (line.rstrip().endswith("") or line.rstrip().endswith("")): @@ -68,12 +69,13 @@ def __parse_xml_input(xml_fd): # entry exists already! merge the two entries pass else: + tmp = node.get("id") cu_dict[node.get("id")] = node return cu_dict -def __map_dummy_nodes(cu_dict): +def __map_dummy_nodes(cu_dict: Dict[str, ObjectifiedElement]) -> Dict[str, ObjectifiedElement]: dummy_node_args_to_id_map = defaultdict(list) func_node_args_to_id_map = dict() dummy_to_func_ids_map = dict() @@ -208,12 +210,14 @@ def __parse_dep_file(dep_fd: TextIOWrapper, output_path: str) -> Tuple[List[Depe return dependencies_list, loop_data_list -def parse_inputs(cu_file, dependencies, reduction_file, file_mapping): +def parse_inputs( + cu_file: str, dependencies_file_path: str, reduction_file: str, file_mapping: str +) -> Tuple[Dict[str, ObjectifiedElement], List[DependenceItem], Dict[str, LoopData], Optional[List[Dict[str, str]]]]: with open(cu_file) as f: cu_dict = __parse_xml_input(f) cu_dict = __map_dummy_nodes(cu_dict) - with open(dependencies) as f: + with open(dependencies_file_path) as f: dependencies, loop_info = __parse_dep_file(f, dirname(abspath(cu_file))) loop_data = {loop.line_id: loop for loop in loop_info} @@ -245,7 +249,7 @@ def parse_inputs(cu_file, dependencies, reduction_file, file_mapping): return cu_dict, dependencies, loop_data, reduction_vars -def is_reduction(reduction_line, fmap_lines, file_mapping): +def is_reduction(reduction_line: str, fmap_lines: List[str], file_mapping: str) -> bool: rex = re.compile("FileID : ([0-9]*) Loop Line Number : [0-9]* Reduction Line Number : ([0-9]*) ") if not rex: return False @@ -265,7 +269,7 @@ def is_reduction(reduction_line, fmap_lines, file_mapping): return possible_reduction(file_line, src_lines) -def possible_reduction(line, src_lines): +def possible_reduction(line: int, src_lines: List[str]) -> bool: assert line > 0 and line <= len(src_lines), "invalid src line" src_line = src_lines[line - 1] while not ";" in src_line: @@ -299,7 +303,7 @@ def possible_reduction(line, src_lines): return True -def get_filepath(file_id, fmap_lines, file_mapping): +def get_filepath(file_id: int, fmap_lines: List[str], file_mapping: str) -> str: assert file_id > 0 and file_id <= len(fmap_lines), "invalid file id" line = fmap_lines[file_id - 1] tokens = line.split(sep="\t") @@ -309,7 +313,7 @@ def get_filepath(file_id, fmap_lines, file_mapping): return tokens[1] -def get_enclosed_str(data): +def get_enclosed_str(data: str) -> str: num_open_brackets = 1 for i in range(0, len(data)): if data[i] == "[": @@ -318,10 +322,11 @@ def get_enclosed_str(data): num_open_brackets = num_open_brackets - 1 if num_open_brackets == 0: return data[0:i] + raise ValueError("No enclosed str found!") -def find_array_indices(array_name, src_line): - indices = [] +def find_array_indices(array_name: str, src_line: str) -> List[str]: + indices: List[str] = [] uses = list(re.finditer(array_name, src_line)) for use in uses: if src_line[use.end()] == "[": diff --git a/discopop_explorer/pattern_detection.py b/discopop_explorer/pattern_detection.py index e2767d2de..cfb24a81f 100644 --- a/discopop_explorer/pattern_detection.py +++ b/discopop_explorer/pattern_detection.py @@ -12,6 +12,7 @@ from alive_progress import alive_bar # type: ignore +from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import VarName from discopop_explorer.pattern_detectors.task_parallelism.task_parallelism_detector import ( build_preprocessed_graph_and_run_detection as detect_tp, ) @@ -194,20 +195,20 @@ def detect_patterns( def load_existing_doall_and_reduction_patterns( self, - project_path, - cu_dict, - dependencies, - loop_data, - reduction_vars, - file_mapping, - cu_inst_result_file, - llvm_cxxfilt_path, - discopop_build_path, - enable_patterns, - enable_task_pattern, - enable_detection_of_scheduling_clauses, - hotspots, - ): + project_path: str, + cu_dict: str, + dependencies: str, + loop_data: str, + reduction_vars: str, + file_mapping: Optional[str], + cu_inst_result_file: Optional[str], + llvm_cxxfilt_path: Optional[str], + discopop_build_path: Optional[str], + enable_patterns: str, + enable_task_pattern: bool, + enable_detection_of_scheduling_clauses: bool, + hotspots: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]]], + ) -> DetectionResult: """skips the pattern discovery on the CU graph and loads a pre-existing pattern file""" self.__merge(False, True) self.pet.map_static_and_dynamic_dependencies() @@ -235,12 +236,12 @@ def load_existing_doall_and_reduction_patterns( print("PATTERNS:") print(pattern_contents) - def __get_var_obj_from_name(name): - return Variable(type="", name=name, defLine="", accessMode="", sizeInByte="0") + def __get_var_obj_from_name(name: VarName) -> Variable: + return Variable(type="", name=name, defLine="", accessMode="", sizeInByte=0) - def __get_red_var_obj_from_name(name): + def __get_red_var_obj_from_name(name: str) -> Variable: split_name = name.split(":") - v = Variable(type="", name=split_name[0], defLine="", accessMode="", sizeInByte="0") + v = Variable(type="", name=VarName(split_name[0]), defLine="", accessMode="", sizeInByte=0) v.operation = split_name[1] return v diff --git a/discopop_explorer/pattern_detectors/PatternBase.py b/discopop_explorer/pattern_detectors/PatternBase.py index 8861843b7..aad4ae694 100644 --- a/discopop_explorer/pattern_detectors/PatternBase.py +++ b/discopop_explorer/pattern_detectors/PatternBase.py @@ -44,7 +44,7 @@ def __init__(self, node: Node): self.end_line = node.end_position() self.applicable_pattern = True - def to_json(self): + def to_json(self) -> str: dic = self.__dict__ keys = [k for k in dic.keys()] for key in keys: diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py index b49df0244..a73feae8b 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py @@ -57,8 +57,10 @@ identify_end_of_life_points, add_aliases, extend_region_liveness_using_unrolled_functions, + join_entryPoint_elements, + join_exitPoint_elements, + join_update_elements, remove_duplicates, - join_elements, ) from discopop_explorer.pattern_detectors.simple_gpu_patterns.GPURegions import GPURegionInfo @@ -310,9 +312,9 @@ def __init__(self, pet: PEGraphX, contained_regions: List[GPURegionInfo], projec exit_points = cast(Set[ExitPoint], remove_duplicates(exit_points)) # join entries - updates = join_elements(updates) - entry_points = join_elements(entry_points) - exit_points = join_elements(exit_points) + updates = join_update_elements(updates) + entry_points = join_entryPoint_elements(entry_points) + exit_points = join_exitPoint_elements(exit_points) # ### PREPARE METADATA # prepare device liveness @@ -354,7 +356,7 @@ def __init__(self, pet: PEGraphX, contained_regions: List[GPURegionInfo], projec self.data_region_depend_in, self.data_region_depend_out = get_dependencies_as_metadata(pet, all_dependencies) - def __str__(self): + def __str__(self) -> str: raise NotImplementedError() # used to identify necessity to call to_string() instead def to_string(self, pet: PEGraphX) -> str: diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Dependency.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Dependency.py index 0b5225f43..712c66915 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Dependency.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Dependency.py @@ -32,7 +32,7 @@ def __init__( self.var_names = var_names self.memory_regions = memory_regions - def __str__(self): + def __str__(self) -> str: return ( "Dependency(" + self.source diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py index 7ad1ed032..18556bcf6 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py @@ -52,7 +52,7 @@ def __init__( self.entry_point_positioning = EntryPointPositioning.BEFORE_CU self.dependencies = set() - def __str__(self): + def __str__(self) -> str: return ( "EntryPoint(" + str(self.var_names) @@ -67,7 +67,9 @@ def __str__(self): + ")" ) - def __eq__(self, other): + def __eq__(self, other: object) -> bool: + if not isinstance(other, EntryPoint): + raise TypeError() if ( tuple(self.var_names), # tuple(self.memory_regions), # leads to duplicated outputs @@ -90,7 +92,7 @@ def __eq__(self, other): return True return False - def __hash__(self): + def __hash__(self) -> int: return hash( ( tuple(self.var_names), @@ -104,7 +106,7 @@ def __hash__(self): ) ) - def get_position_identifier(self): + def get_position_identifier(self) -> Tuple[NodeID, NodeID, EntryPointType, EntryPointPositioning]: # used to join multiple elements return ( self.sink_cu_id, @@ -113,7 +115,7 @@ def get_position_identifier(self): self.entry_point_positioning, ) - def join(self, other): + def join(self, other: EntryPoint) -> None: self.var_names.update(other.var_names) self.memory_regions.update(other.memory_regions) self.dependencies.update(other.dependencies) diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py index ed8388e9a..ce242cdc7 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py @@ -5,6 +5,7 @@ # This software may be modified and distributed under the terms of # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. +from __future__ import annotations import os from typing import Set, List, Tuple @@ -50,7 +51,7 @@ def __init__( self.exit_point_positioning = ExitPointPositioning.BEFORE_CU self.dependencies = set() - def __str__(self): + def __str__(self) -> str: return ( "ExitPoint(" + str(self.var_names) @@ -65,7 +66,9 @@ def __str__(self): + ")" ) - def __eq__(self, other): + def __eq__(self, other: object) -> bool: + if not isinstance(other, ExitPoint): + raise TypeError() if ( tuple(self.var_names), # tuple(self.memory_regions), # leads to duplicated outputs @@ -88,7 +91,7 @@ def __eq__(self, other): return True return False - def __hash__(self): + def __hash__(self) -> int: return hash( ( tuple(self.var_names), @@ -102,7 +105,7 @@ def __hash__(self): ) ) - def get_position_identifier(self): + def get_position_identifier(self) -> Tuple[NodeID, NodeID, ExitPointType, ExitPointPositioning]: # used to join multiple elements return ( self.sink_cu_id, @@ -111,7 +114,7 @@ def get_position_identifier(self): self.exit_point_positioning, ) - def join(self, other): + def join(self, other: ExitPoint) -> None: self.var_names.update(other.var_names) self.memory_regions.update(other.memory_regions) self.dependencies.update(other.dependencies) diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py index d68561e59..49a6e2581 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py @@ -5,6 +5,7 @@ # This software may be modified and distributed under the terms of # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. +from __future__ import annotations import os from typing import Set, Dict, cast, Optional, List, Tuple @@ -81,7 +82,7 @@ def __init__( # ) # ) - def __str__(self): + def __str__(self) -> str: result_str = "" result_str += ( str(self.update_type) @@ -101,7 +102,9 @@ def __str__(self): ) return result_str - def __eq__(self, other): + def __eq__(self, other: object) -> bool: + if not isinstance(other, Update): + raise ValueError("other is not of correct type!") if ( self.synchronous_source_cu_id, self.asynchronous_source_cu_id, @@ -126,7 +129,7 @@ def __eq__(self, other): return True return False - def __hash__(self): + def __hash__(self) -> int: return hash( ( self.synchronous_source_cu_id, @@ -287,7 +290,7 @@ def convert_memory_regions_to_variable_names( else: self.variable_names.add(VarName("UNDETERMINED(" + mem_reg + ")")) - def remove_dummy_marks(self): + def remove_dummy_marks(self) -> None: if self.sink_cu_id.startswith("dummy:"): self.sink_cu_id = NodeID(self.sink_cu_id[6:]) if self.synchronous_source_cu_id.startswith("dummy:"): diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py index 22d646871..47a4d65a6 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py @@ -39,7 +39,7 @@ def __init__(self, cu_id: NodeID, device_id: int): self.seen_writes_by_device = dict() self.print() - def __str__(self): + def __str__(self) -> str: result_str = "" result_str += "Context:\n" result_str += "\tcu_id: " + str(self.cu_id) + "\n" @@ -55,7 +55,7 @@ def __str__(self): result_str += "\n" return result_str - def print(self): + def print(self) -> None: print(self, file=sys.stderr) def update_writes( diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py index 944b1b97d..a615454cb 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py @@ -7,7 +7,7 @@ # directory for details. import copy import sys -from typing import Any, Set, Tuple, Dict, List, cast, Optional, Union +from typing import Any, Set, Tuple, Dict, List, TypeVar, cast, Optional, Union, overload from networkx import MultiDiGraph # type: ignore @@ -355,7 +355,7 @@ def remove_duplicates( return target_set -def join_elements(target_set): +def join_update_elements(target_set: Set[Update]) -> Set[Update]: grouping_dict: Dict[Any, List[Any]] = dict() for elem in target_set: @@ -367,7 +367,30 @@ def join_elements(target_set): for key in grouping_dict: # assemble a single EntryPoint - joined_entry_point: Optional[EntryPoint] = None + joined_entry_point = None + for elem in grouping_dict[key]: + if joined_entry_point is None: + joined_entry_point = elem + else: + joined_entry_point.join(elem) + result_set.add(cast(Update, joined_entry_point)) + + return result_set + + +def join_entryPoint_elements(target_set: Set[EntryPoint]) -> Set[EntryPoint]: + grouping_dict: Dict[Any, List[Any]] = dict() + + for elem in target_set: + if elem.get_position_identifier() not in grouping_dict: + grouping_dict[elem.get_position_identifier()] = [] + grouping_dict[elem.get_position_identifier()].append(elem) + + result_set = set() + + for key in grouping_dict: + # assemble a single EntryPoint + joined_entry_point = None for elem in grouping_dict[key]: if joined_entry_point is None: joined_entry_point = elem @@ -376,3 +399,26 @@ def join_elements(target_set): result_set.add(cast(EntryPoint, joined_entry_point)) return result_set + + +def join_exitPoint_elements(target_set: Set[ExitPoint]) -> Set[ExitPoint]: + grouping_dict: Dict[Any, List[Any]] = dict() + + for elem in target_set: + if elem.get_position_identifier() not in grouping_dict: + grouping_dict[elem.get_position_identifier()] = [] + grouping_dict[elem.get_position_identifier()].append(elem) + + result_set = set() + + for key in grouping_dict: + # assemble a single EntryPoint + joined_entry_point = None + for elem in grouping_dict[key]: + if joined_entry_point is None: + joined_entry_point = elem + else: + joined_entry_point.join(elem) + result_set.add(cast(ExitPoint, joined_entry_point)) + + return result_set diff --git a/discopop_explorer/pattern_detectors/device_updates.py b/discopop_explorer/pattern_detectors/device_updates.py index 309dd34b8..b2aa0e42d 100644 --- a/discopop_explorer/pattern_detectors/device_updates.py +++ b/discopop_explorer/pattern_detectors/device_updates.py @@ -53,7 +53,7 @@ def __init__( self.openmp_source_device_id = openmp_source_device_id self.openmp_target_device_id = openmp_target_device_id - def __str__(self): + def __str__(self) -> str: return ( # f"Device update at: {self.node_id}\n" # removed to allow reduction of duplicates in the generated OpenMP code in CodeGenerator f"Start line: {self.start_line}\n" diff --git a/discopop_explorer/pattern_detectors/do_all_detector.py b/discopop_explorer/pattern_detectors/do_all_detector.py index 2cf46a9c2..df6c7f387 100644 --- a/discopop_explorer/pattern_detectors/do_all_detector.py +++ b/discopop_explorer/pattern_detectors/do_all_detector.py @@ -50,7 +50,7 @@ def __init__(self, pet: PEGraphX, node: Node): self.scheduling_clause = "static" self.collapse_level = 1 - def __str__(self): + def __str__(self) -> str: return ( f"Do-all at: {self.node_id}\n" f"Start line: {self.start_line}\n" @@ -119,12 +119,12 @@ def run_detection( return result -def __initialize_worker(pet): +def __initialize_worker(pet: PEGraphX) -> None: global global_pet global_pet = pet -def __check_node(param_tuple): +def __check_node(param_tuple: LoopNode) -> List[DoAllInfo]: global global_pet local_result = [] node = param_tuple diff --git a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py index 929d0b4b5..be004f323 100644 --- a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py +++ b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py @@ -10,6 +10,7 @@ import math from typing import Dict, List, Tuple, Optional, cast +from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import VarName from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore @@ -50,7 +51,7 @@ def __init__(self, pet: PEGraphX, node: Node, min_iter: int): self.pragma = "for (i = 0; i < num-tasks; i++) #pragma omp task" lp: List[Variable] = [] fp, p, s, in_dep, out_dep, in_out_dep, r = classify_task_vars(pet, node, "GeometricDecomposition", [], []) - fp.append(Variable("int", "i", "", sizeInByte=4)) + fp.append(Variable("int", VarName("i"), "", sizeInByte=4)) self.first_private = fp self.private = p @@ -58,7 +59,7 @@ def __init__(self, pet: PEGraphX, node: Node, min_iter: int): self.shared = s self.reduction = r - def __str__(self): + def __str__(self) -> str: return ( f"Geometric decomposition at: {self.node_id}\n" f"Start line: {self.start_line}\n" @@ -113,14 +114,14 @@ def run_detection( return result -def __initialize_worker(pet): +def __initialize_worker(pet: PEGraphX) -> None: global global_pet global_pet = pet -def __check_node(param_tuple): +def __check_node(param_tuple: Node) -> List[GDInfo]: global global_pet - local_result = [] + local_result: List[GDInfo] = [] node = param_tuple if global_pet is None: raise ValueError("global_pet is None!") diff --git a/discopop_explorer/pattern_detectors/pipeline_detector.py b/discopop_explorer/pattern_detectors/pipeline_detector.py index e34ed388a..1646cd878 100644 --- a/discopop_explorer/pattern_detectors/pipeline_detector.py +++ b/discopop_explorer/pattern_detectors/pipeline_detector.py @@ -51,7 +51,7 @@ def __init__( self.out_deps = out_deps self.in_out_deps = in_out_deps - def __str__(self): + def __str__(self) -> str: return ( f"\tNode: {self.node}\n" f"\tStart line: {self.startsAtLine}\n" @@ -119,7 +119,7 @@ def __output_stage(self, node: Node) -> PipelineStage: return PipelineStage(self._pet, node, in_d, out_d) - def __str__(self): + def __str__(self) -> str: s = "\n\n".join([str(s) for s in self.stages]) return ( f"Pipeline at: {self.node_id}\n" @@ -188,12 +188,12 @@ def run_detection( return result -def __initialize_worker(pet): +def __initialize_worker(pet: PEGraphX) -> None: global global_pet global_pet = pet -def __check_node(param_tuple): +def __check_node(param_tuple: LoopNode) -> List[PipelineInfo]: global global_pet local_result = [] diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index 24535f357..345fae5f8 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -50,7 +50,7 @@ def __init__(self, pet: PEGraphX, node: Node): self.shared = s self.reduction = r - def __str__(self): + def __str__(self) -> str: return ( f"Reduction at: {self.node_id}\n" f"Start line: {self.start_line}\n" @@ -100,14 +100,14 @@ def run_detection( return result -def __initialize_worker(pet): +def __initialize_worker(pet: PEGraphX) -> None: global global_pet global_pet = pet -def __check_node(param_tuple): +def __check_node(param_tuple: LoopNode) -> List[ReductionInfo]: global global_pet - local_result = [] + local_result: List[ReductionInfo] = [] node = param_tuple if global_pet is None: raise ValueError("global_pet is None!") diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py index 0276e4d9b..4f28144fa 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py @@ -218,7 +218,7 @@ def __init__( self.constructs = [] self.declared_global_variables: Set[Variable] = set() - def __str__(self): + def __str__(self) -> str: raise NotImplementedError() # used to identify necessity to call to_string() instead def to_string(self, pet: PEGraphX) -> str: @@ -430,12 +430,14 @@ def __get_constructs( self.declared_global_variables.update(used_global_vars) for global_var in used_global_vars: constructs.append( - omp_construct_dict("#pragma omp declare target // " + str(global_var.name), global_var.defLine, []) + omp_construct_dict( + "#pragma omp declare target // " + str(global_var.name), LineID(global_var.defLine), [] + ) ) constructs.append( omp_construct_dict( "#pragma omp end declare target // " + str(global_var.name), - global_var.defLine, + LineID(global_var.defLine), [], positioning=OmpConstructPositioning.AFTER_LINE, ) diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py index 077ceaf4d..5355c6a27 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py @@ -69,7 +69,7 @@ def __init__( self.end_line = max([l.end_line for l in contained_loops]) self.project_folder_path = project_folder_path - def __str__(self): + def __str__(self) -> str: raise NotImplementedError() # used to identify necessity to call to_string() instead def to_string(self, pet: PEGraphX) -> str: @@ -141,7 +141,7 @@ class GPURegions: consumed_vars: Dict[Tuple[str, ...], List[str]] project_folder_path: str - def __init__(self, pet, gpu_patterns, project_folder_path): + def __init__(self, pet: PEGraphX, gpu_patterns: List[GPULoopPattern], project_folder_path: str): self.loopsInRegion = [] self.gpu_loop_patterns = gpu_patterns self.project_folder_path = project_folder_path diff --git a/discopop_explorer/pattern_detectors/task_parallelism/classes.py b/discopop_explorer/pattern_detectors/task_parallelism/classes.py index c1246c828..19b64b0b5 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/classes.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/classes.py @@ -108,7 +108,7 @@ def __init__( self.atomic_sections: List[str] = [] self.task_group: List[int] = [] - def __str__(self): + def __str__(self) -> str: return ( f"Task parallelism at CU: {self.node_id}\n" f"CU Start line: {self.start_line}\n" @@ -139,7 +139,7 @@ def __init__(self, node: Node, type: TPIType, region_start_line: LineID, region_ self.pragma = "#pragma omp parallel\n\t#pragma omp single" self.type = type - def __str__(self): + def __str__(self) -> str: return ( f"Task Parallel Region at CU: {self.node_id}\n" f"CU Start line: {self.start_line}\n" @@ -166,7 +166,7 @@ def __init__(self, node: Node, combine_with_node: Node): self.out_dep: List[Optional[str]] = [] self.in_out_dep: List[Optional[str]] = [] - def __str__(self): + def __str__(self) -> str: return ( f"Omittable CU: {self.node_id}\n" f"CU Start line: {self.start_line}\n" diff --git a/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py b/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py index d041fb8a2..e636d2db6 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py @@ -203,7 +203,7 @@ def cu_xml_preprocessing(cu_xml: str) -> str: return modified_cu_xml -def __generate_new_cu_id(parent, parent_copy, used_node_ids, self_added_node_ids): +def __generate_new_cu_id(parent: Any, parent_copy: Any, used_node_ids: Any, self_added_node_ids: Any) -> None: """Generate the next free CU id and assign it to the parent CU. :param parent: parent CU, id will be updated :param parent_copy: copy of parent CU (newly created CU) @@ -219,7 +219,7 @@ def __generate_new_cu_id(parent, parent_copy, used_node_ids, self_added_node_ids self_added_node_ids.append(incremented_id) -def __set_parent_copy_childrennodes(parent_copy): +def __set_parent_copy_childrennodes(parent_copy: Any) -> None: """Adds cu nodes called by parent_copy to the childrenNodes list of parent_copy, if not already contained. :param parent_copy: cu node to be updated""" parent_copy.childrenNodes._setText("") @@ -242,7 +242,7 @@ def __set_parent_copy_childrennodes(parent_copy): continue -def __remove_overlapping_start_and_end_lines(parent_copy, target_list): +def __remove_overlapping_start_and_end_lines(parent_copy: Any, target_list: Any) -> None: """Removes the first line of parent_copy from parent´s readPhaseLines, writePhaseLines or instructionLines. As a result, start and end Lines of both nodes do not overlap anymore. :param parent_copy: copy of parent node (newly added node) @@ -258,7 +258,7 @@ def __remove_overlapping_start_and_end_lines(parent_copy, target_list): target_list.set("count", "1") -def __filter_rwi_lines(parent_copy, target_list): +def __filter_rwi_lines(parent_copy: Any, target_list: Any) -> None: """Removes entries from instructionLines, readPhaseLines and writePhraseLines of parent_copy if their value is not between parent_copy.startsAtLine and parent_copy.endsAtLine. :param parent_copy: cu node to be filtered @@ -275,7 +275,7 @@ def __filter_rwi_lines(parent_copy, target_list): pass -def __insert_separator_line(parent_copy, target_list): +def __insert_separator_line(parent_copy: Any, target_list: Any) -> None: """Insert separator line to parent_copys instruction, read and writePhaseLines if not already present :param parent_copy: cu node to be updated :param target_list: eiter readPhaseLines, writePhaseLines or instructionLines of parent_copy""" @@ -291,7 +291,7 @@ def __insert_separator_line(parent_copy, target_list): target_list._setText(target_list.text.replace(",,", ",")) -def __insert_missing_rwi_lines(parent, target_list): +def __insert_missing_rwi_lines(parent: Any, target_list: Any) -> None: """Insert all lines contained in parent to instruction, read and writePhaseLines :param parent: cu node to be updated :param target_list: eiter readPhaseLines, writePhaseLines or instructionLines of parent""" @@ -308,7 +308,7 @@ def __insert_missing_rwi_lines(parent, target_list): target_list._setText(target_list.text.replace(",,", ",")) -def __remove_unnecessary_return_instructions(target): +def __remove_unnecessary_return_instructions(target: Any) -> None: """Remove returnInstructions if they are not part of target cu anymore. :param target: cu to be checked""" if int(target.returnInstructions.get("count")) != 0: @@ -321,7 +321,7 @@ def __remove_unnecessary_return_instructions(target): target.returnInstructions.set("count", str(len(new_entries))) -def __add_parent_id_to_children(parsed_cu, parent): +def __add_parent_id_to_children(parsed_cu: Any, parent: Any) -> None: """ "Add parent.id to parent_function.childrenNodes :param: parsed_cu: parsed contents of cu_xml file :param parent: cu node to be added to parent_function's children diff --git a/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py b/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py index 386740d49..abfdf27e1 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py @@ -102,7 +102,7 @@ def build_preprocessed_graph_and_run_detection( set_global_llvm_cxxfilt_path(__global_llvm_cxxfilt_path) preprocessed_cu_xml = cu_xml_preprocessing(cu_xml) preprocessed_graph = PEGraphX.from_parsed_input( - *parse_inputs(preprocessed_cu_xml, dep_file, reduction_file, file_mapping) + *parse_inputs(preprocessed_cu_xml, dep_file, reduction_file, file_mapping) # type: ignore ) # execute reduction detector to enable taskloop-reduction-detection diff --git a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py index 9039e83c6..adc7cace9 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py @@ -399,13 +399,13 @@ def get_function_call_from_source_code( if ")" in function_call_string and "(" not in function_call_string: function_call_string = function_call_string[function_call_string.index(")") + 1 :] - def __get_word_prior_to_bracket(string): + def __get_word_prior_to_bracket(string: str) -> Optional[str]: if "(" not in string: return None string = string[: string.index("(")] - string = string.split(" ") - string = [e for e in string if len(e) > 0] - string = string[-1] + split_string = string.split(" ") + split_string = [e for e in split_string if len(e) > 0] + string = split_string[-1] return string called_function_name_contained = called_function_name is None diff --git a/discopop_explorer/plugins/pipeline.py b/discopop_explorer/plugins/pipeline.py index 919a3ef89..1761aa50f 100644 --- a/discopop_explorer/plugins/pipeline.py +++ b/discopop_explorer/plugins/pipeline.py @@ -93,7 +93,7 @@ def check_pipeline(pet: PEGraphX, root: Node) -> None: print(" ".join([str(x) for x in matrix[i]])) -def delete_lines(matrix, loop_nodes, lines): +def delete_lines(matrix: List[List[int]], loop_nodes: List[Node], lines: List[int]) -> None: if lines: lines.sort(reverse=True) for i in range(0, len(lines)): @@ -103,8 +103,8 @@ def delete_lines(matrix, loop_nodes, lines): del matrix[j][lines[i]] -def get_independent_lines(matrix): - res = [] +def get_independent_lines(matrix: List[List[int]]) -> List[int]: + res: List[int] = [] for i in range(0, len(matrix)): indep = True for j in range(0, len(matrix)): @@ -115,8 +115,8 @@ def get_independent_lines(matrix): return res -def get_mergeable_nodes(matrix): - res = [] +def get_mergeable_nodes(matrix: List[List[int]]) -> List[int]: + res: List[int] = [] for i in reversed(range(1, len(matrix))): if matrix[i] == matrix[i - 1]: same = True @@ -137,8 +137,8 @@ def get_matrix(pet: PEGraphX, root: Node, loop_subnodes: List[Node]) -> List[Lis return res -def get_correlation_coefficient(matrix): - graph_vector = [] +def get_correlation_coefficient(matrix: List[List[int]]) -> float: + graph_vector: List[float] = [] for i in range(0, len(matrix) - 1): graph_vector.append(matrix[i + 1][i]) diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index 012b7c915..b7c66de86 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -6,7 +6,7 @@ # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. import itertools -from typing import List, Optional, Sequence, Set, Dict, Tuple, cast +from typing import Callable, List, Optional, Sequence, Set, Dict, Tuple, TypeVar, cast import numpy as np import warnings @@ -33,8 +33,10 @@ loop_data: Dict[LineID, int] = {} +T = TypeVar("T") -def contains(list, filter): + +def contains(list: List[T], filter: Callable[[T], bool]) -> bool: for x in list: if filter(x): return True @@ -341,7 +343,7 @@ def is_scalar_val(var: Variable) -> bool: :param var: variable :return: true if scalar """ - return not (var.type.endswith("**") or var.type.startswith("ARRAY" or var.type.startswith("["))) + return not (var.type.endswith("**") or var.type.startswith("ARRAY") or var.type.startswith("[")) def is_readonly( diff --git a/discopop_explorer/variable.py b/discopop_explorer/variable.py index fbd5de32a..7e00ca74b 100644 --- a/discopop_explorer/variable.py +++ b/discopop_explorer/variable.py @@ -5,6 +5,7 @@ # This software may be modified and distributed under the terms of # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. +from __future__ import annotations from typing import Optional from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import VarName @@ -13,7 +14,7 @@ class Variable(object): operation: Optional[str] - def __init__(self, type, name, defLine, accessMode="", sizeInByte=0): + def __init__(self, type: str, name: VarName, defLine: str, accessMode: str = "", sizeInByte: int = 0): self.type = type self.name: VarName = name self.defLine = defLine @@ -26,22 +27,22 @@ def __init__(self, type, name, defLine, accessMode="", sizeInByte=0): sizeInByte = 8 self.sizeInByte = sizeInByte - def __hash__(self): + def __hash__(self) -> int: return hash(self.name) - def __eq__(self, other): + def __eq__(self, other: object) -> bool: return isinstance(other, Variable) and self.name == other.name - def __lt__(self, other): + def __lt__(self, other: Variable) -> bool: try: return self.name < other.name except: return True - def __str__(self): + def __str__(self) -> str: return self.name - def toJSON(self): + def toJSON(self) -> str: if self.operation is None: return self.name else: diff --git a/discopop_library/CodeGenerator/CodeGeneratorArguments.py b/discopop_library/CodeGenerator/CodeGeneratorArguments.py index e5b0d77d9..652062f41 100644 --- a/discopop_library/CodeGenerator/CodeGeneratorArguments.py +++ b/discopop_library/CodeGenerator/CodeGeneratorArguments.py @@ -19,11 +19,11 @@ class CodeGeneratorArguments(object): skip_compilation_check: bool compile_check_command: str - def __post_init__(self): + def __post_init__(self) -> None: self.__validate() - def __validate(self): + def __validate(self) -> None: pass - def __str__(self): + def __str__(self) -> str: return str(self.__dict__) diff --git a/discopop_library/CodeGenerator/classes/Pragma.py b/discopop_library/CodeGenerator/classes/Pragma.py index 973475021..75913f067 100644 --- a/discopop_library/CodeGenerator/classes/Pragma.py +++ b/discopop_library/CodeGenerator/classes/Pragma.py @@ -20,5 +20,5 @@ class Pragma(object): parent_cu_id: str = "" children: List[Any] = [] - def __init__(self): + def __init__(self) -> None: self.children = [] # create individual list for each Pragma object to prevent bugs due to mutability diff --git a/discopop_library/CodeGenerator/classes/UnpackedSuggestion.py b/discopop_library/CodeGenerator/classes/UnpackedSuggestion.py index 9eba29847..581e32de5 100644 --- a/discopop_library/CodeGenerator/classes/UnpackedSuggestion.py +++ b/discopop_library/CodeGenerator/classes/UnpackedSuggestion.py @@ -61,7 +61,7 @@ def __init__( if self.values["device_type"] is not None: self.device_type = self.values["device_type"] - def __get_device_update_pragmas(self): + def __get_device_update_pragmas(self) -> List[Pragma]: pragmas = [] pragma = Pragma() @@ -75,7 +75,7 @@ def __get_device_update_pragmas(self): delete_data: bool = self.values["delete_data"] copy_delete_data: bool = self.values["copy_delete_data"] - def get_range_str(r): + def get_range_str(r: Optional[Tuple[int, int]]) -> str: return "" if r is None else "[" + str(r[0]) + ":" + str(r[1]) + "]" if source_device_id == self.host_device_id and target_device_id == self.host_device_id: diff --git a/discopop_library/ConfigProvider/ConfigProviderArguments.py b/discopop_library/ConfigProvider/ConfigProviderArguments.py index fe9ec0937..e131f42f3 100644 --- a/discopop_library/ConfigProvider/ConfigProviderArguments.py +++ b/discopop_library/ConfigProvider/ConfigProviderArguments.py @@ -18,11 +18,11 @@ class ConfigProviderArguments(object): return_full_config: bool return_version_string: bool - def __post_init__(self): + def __post_init__(self) -> None: self.__validate() - def __validate(self): + def __validate(self) -> None: pass - def __str__(self): + def __str__(self) -> str: return str(self.__dict__) diff --git a/discopop_library/DependencyMetadata/compare_metadata.py b/discopop_library/DependencyMetadata/compare_metadata.py index 852f28320..ecea23e61 100644 --- a/discopop_library/DependencyMetadata/compare_metadata.py +++ b/discopop_library/DependencyMetadata/compare_metadata.py @@ -9,7 +9,7 @@ from typing import Set -def main(): +def main() -> None: gold_result_path = "/home/lukas/dependency_metadata.txt" gold_standard: Set[str] = set() diff --git a/discopop_library/HostpotLoader/HotspotLoaderArguments.py b/discopop_library/HostpotLoader/HotspotLoaderArguments.py index 6a02859d8..1ffa5a056 100644 --- a/discopop_library/HostpotLoader/HotspotLoaderArguments.py +++ b/discopop_library/HostpotLoader/HotspotLoaderArguments.py @@ -22,13 +22,13 @@ class HotspotLoaderArguments(GeneralArguments): get_NO: bool get_MAYBE: bool - def __post_init__(self): + def __post_init__(self) -> None: self.__validate() - def __validate(self): + def __validate(self) -> None: pass - def __str__(self): + def __str__(self) -> str: return str(self.__dict__) def get_considered_hotness(self) -> List[str]: diff --git a/discopop_library/PatchApplicator/PatchApplicatorArguments.py b/discopop_library/PatchApplicator/PatchApplicatorArguments.py index b7ae40da4..aa3c01370 100644 --- a/discopop_library/PatchApplicator/PatchApplicatorArguments.py +++ b/discopop_library/PatchApplicator/PatchApplicatorArguments.py @@ -24,10 +24,10 @@ class PatchApplicatorArguments(GeneralArguments): load: bool list: bool - def __post_init__(self): + def __post_init__(self) -> None: self.__validate() - def __validate(self): + def __validate(self) -> None: """Validate the arguments passed to the discopop_patch_applicator, e.g check if given files exist""" # check mutually exclusive arguments exit_required = False diff --git a/discopop_library/PatchGenerator/PatchGeneratorArguments.py b/discopop_library/PatchGenerator/PatchGeneratorArguments.py index 3596ec7c0..00be5dc84 100644 --- a/discopop_library/PatchGenerator/PatchGeneratorArguments.py +++ b/discopop_library/PatchGenerator/PatchGeneratorArguments.py @@ -24,10 +24,10 @@ class PatchGeneratorArguments(GeneralArguments): only_optimizer_output_patterns: bool only_maximum_id_pattern: bool - def __post_init__(self): + def __post_init__(self) -> None: self.__validate() - def __validate(self): + def __validate(self) -> None: """Validate the arguments passed to the discopop_explorer, e.g check if given files exist""" if self.verbose: print("Configuration:") diff --git a/discopop_library/PatchGenerator/__main__.py b/discopop_library/PatchGenerator/__main__.py index 9aac4ad38..f1f821576 100644 --- a/discopop_library/PatchGenerator/__main__.py +++ b/discopop_library/PatchGenerator/__main__.py @@ -96,7 +96,7 @@ def parse_args() -> PatchGeneratorArguments: ) -def main(): +def main() -> None: arguments = parse_args() setup_logger(arguments) run(arguments) diff --git a/discopop_library/discopop_optimizer/CostModels/CostModel.py b/discopop_library/discopop_optimizer/CostModels/CostModel.py index 395ba4300..19d4daf88 100644 --- a/discopop_library/discopop_optimizer/CostModels/CostModel.py +++ b/discopop_library/discopop_optimizer/CostModels/CostModel.py @@ -8,14 +8,21 @@ from __future__ import annotations import random import sys -from typing import List, Dict, Tuple, Optional +from typing import Any, List, Dict, TextIO, Tuple, Optional import numpy as np import sympy from matplotlib import pyplot as plt # type: ignore from sympy import Function, Symbol, init_printing, Expr, N, nsimplify, Integer # type: ignore +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from discopop_library.discopop_optimizer.Variables.Experiment import Experiment + from discopop_library.discopop_optimizer.classes.nodes.FunctionRoot import FunctionRoot + from discopop_library.discopop_optimizer.classes.nodes.GenericNode import GenericNode from discopop_library.discopop_optimizer.classes.enums.Distributions import FreeSymbolDistribution +from discopop_library.discopop_optimizer.classes.system.devices.Device import Device class CostModel(object): @@ -29,7 +36,7 @@ class CostModel(object): free_symbol_distributions: Dict[Symbol, FreeSymbolDistribution] symbol_value_suggestions: Dict[Symbol, Expr] - def toJSON(self): + def toJSON(self) -> str: return "AsDF" def __init__( @@ -55,10 +62,10 @@ def __init__( self.parallelizable_costs = parallelizable_costs self.sequential_costs = sequential_costs - def __str__(self): + def __str__(self) -> str: return str(self.parallelizable_costs) + str(self.sequential_costs) - def print(self, file=sys.stdout): + def print(self, file: TextIO = sys.stdout) -> None: init_printing() print("\tPARALLEL:") print("\t", self.parallelizable_costs, file=file) @@ -84,7 +91,7 @@ def parallelizable_plus_combine(self, other: CostModel) -> CostModel: symbol_value_suggestions=value_suggestions, ) - def parallelizable_divide_combine(self, other): + def parallelizable_divide_combine(self, other: CostModel) -> CostModel: """Combines both models in the following fashion: f(x,y) = ==> x.parallelizable_costs / y.parallelizable_costs @@ -102,7 +109,7 @@ def parallelizable_divide_combine(self, other): symbol_value_suggestions=value_suggestions, ) - def parallelizable_multiply_combine(self, other): + def parallelizable_multiply_combine(self, other: CostModel) -> CostModel: """Combines both models in the following fashion: f(x,y) = ==> x.parallelizable_costs * y.parallelizable_costs @@ -121,17 +128,24 @@ def parallelizable_multiply_combine(self, other): symbol_value_suggestions=value_suggestions, ) - def register_child(self, other, root_node, experiment, all_function_nodes, current_device): + def register_child( + self, + other: CostModel, + root_node: GenericNode, + experiment: Experiment, + all_function_nodes: List[FunctionRoot], + current_device: Device, + ) -> CostModel: """Registers a child node for the given model. Does not modify the stored model in self or other.""" return root_node.register_child(other, experiment, all_function_nodes, current_device) - def register_successor(self, other, root_node): + def register_successor(self, other: CostModel, root_node: GenericNode) -> CostModel: """Registers a successor node for the given model. Does not modify the stored model in self or other.""" return root_node.register_successor(other) - def __lt__(self, other): + def __lt__(self, other: CostModel) -> bool: """Compare both models. The comparison is based on random sampling and may not be correct in all cases! """ @@ -225,7 +239,7 @@ def __plot_weibull_distributions(self, alpha: float, beta: float) -> None: """For Debug reasons. Plots the left and right side heavy weibull distributions using the given parameters.""" x = np.arange(1, 100.0) / 100.0 # normalized to [0,1] - def weibull(x, n, a): + def weibull(x: Any, n: float, a: float) -> Any: return (a / n) * (x / n) ** (a - 1) * np.exp(-((x / n) ** a)) plt.plot(x, weibull(x, alpha, beta), label="Alpha: " + str(alpha) + " Beta: " + str(beta)) diff --git a/discopop_library/discopop_optimizer/DataTransfers/NewDataTransfers.py b/discopop_library/discopop_optimizer/DataTransfers/NewDataTransfers.py index 8f1149ae5..b56e70542 100644 --- a/discopop_library/discopop_optimizer/DataTransfers/NewDataTransfers.py +++ b/discopop_library/discopop_optimizer/DataTransfers/NewDataTransfers.py @@ -183,7 +183,7 @@ def perform_write(self, node_id: int, device_id: DeviceID, wda: WriteDataAccess) self.memory[device_id] = dict() self.memory[device_id][wda.memory_region] = wda - def log_state(self): + def log_state(self) -> None: logger.debug("Memory state:") for device_id in self.memory: logger.debug("-> Device: " + str(device_id)) @@ -195,7 +195,7 @@ def log_state(self): class DataFrame(object): entered_data_regions_by_device: Dict[DeviceID, List[WriteDataAccess]] - def __init__(self): + def __init__(self) -> None: self.entered_data_regions_by_device = dict() def parse_update(self, update: Update) -> None: @@ -305,7 +305,7 @@ def cleanup_dataframe(self, node_id: int, memory: DeviceMemory, experiment: Expe return updates - def log_state(self): + def log_state(self) -> None: logger.debug("DataFrame:") for device_id in self.entered_data_regions_by_device: logger.debug("-> Device: " + str(device_id)) diff --git a/discopop_library/discopop_optimizer/Microbench/DelaunayInterpolatedMicrobench.py b/discopop_library/discopop_optimizer/Microbench/DelaunayInterpolatedMicrobench.py index a590fdcfd..676b3a2b9 100644 --- a/discopop_library/discopop_optimizer/Microbench/DelaunayInterpolatedMicrobench.py +++ b/discopop_library/discopop_optimizer/Microbench/DelaunayInterpolatedMicrobench.py @@ -72,8 +72,8 @@ def __getTuples( tuples.append((*benchCoord, np.median(values).item())) return tuples - def __interpolate(self): - def __createInterpolator(tuples): + def __interpolate(self) -> None: + def __createInterpolator(tuples: List[Tuple[int, int | float, int, float]]) -> LinearNDInterpolator: coords = [] values = [] for t in tuples: @@ -86,10 +86,12 @@ def __createInterpolator(tuples): for type, dimMap in self.data.getMeasurements().items() } - def getMeasurements(self): + def getMeasurements( + self, + ) -> Dict[MicrobenchType, Dict[MicrobenchDimension, Dict[MicrobenchCoordinate, List[float]]]]: return self.data.getMeasurements() - def toJSON(self): + def toJSON(self) -> str: return self.data.toJSON() def evaluateInterpolation( diff --git a/discopop_library/discopop_optimizer/Microbench/ExtrapInterpolatedMicrobench.py b/discopop_library/discopop_optimizer/Microbench/ExtrapInterpolatedMicrobench.py index 6a190f2c7..59b65d248 100644 --- a/discopop_library/discopop_optimizer/Microbench/ExtrapInterpolatedMicrobench.py +++ b/discopop_library/discopop_optimizer/Microbench/ExtrapInterpolatedMicrobench.py @@ -5,7 +5,7 @@ # This software may be modified and distributed under the terms of # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. -from typing import Dict, Tuple, Union, cast +from typing import Dict, List, Tuple, Union, cast import sympy @@ -39,7 +39,7 @@ def __init__(self, jsonFile: str): self.models = experiment.modelers[0].models # convenient for debugging: print the model functions - def printModelFunctions(self): + def printModelFunctions(self) -> None: for callpathMetric, model in self.models.items(): test = str(callpathMetric[0]).ljust(12) metric = str(callpathMetric[1]) @@ -75,10 +75,13 @@ def getFunctionSympy( expr = parse_expr(function_str, local_dict=function_mappings) return cast(sympy.Expr, expr) - def getMeasurements(self): + def getMeasurements(self) -> Dict[ + MicrobenchType, + Dict[MicrobenchDimension, Dict[MicrobenchCoordinate, List[float]]], + ]: raise NotImplementedError("TODO") # TODO - def toJSON(self): + def toJSON(self) -> str: raise NotImplementedError("TODO") # TODO def evaluateInterpolation( diff --git a/discopop_library/discopop_optimizer/Microbench/PureDataMicrobench.py b/discopop_library/discopop_optimizer/Microbench/PureDataMicrobench.py index 0aa9f675f..5f2b310ed 100644 --- a/discopop_library/discopop_optimizer/Microbench/PureDataMicrobench.py +++ b/discopop_library/discopop_optimizer/Microbench/PureDataMicrobench.py @@ -9,7 +9,7 @@ import json from dataclasses import dataclass -from typing import Callable, Dict, List, Tuple, TypeVar, Union, overload +from typing import Any, Callable, Dict, List, Tuple, TypeVar, Union, overload import numpy as np @@ -65,7 +65,7 @@ def __getitem__( def __getitem__(self, key: Tuple[MicrobenchType, MicrobenchDimension, MicrobenchCoordinate]) -> List[float]: ... # allow to use this class like a dictionary - def __getitem__(self, key): + def __getitem__(self, key: Any) -> Any: if isinstance(key, MicrobenchType): return self.measurements[key] elif ( @@ -87,7 +87,7 @@ def __getitem__(self, key): raise KeyError("Invalid key type:" + str(type(key))) # allow to use this class like a dictionary - def __setitem__(self, key, value): + def __setitem__(self, key: Any, value: Any) -> None: if isinstance(key, MicrobenchType): if not isinstance(value, Dict): raise ValueError( @@ -119,25 +119,25 @@ def __setitem__(self, key, value): else: raise KeyError("Invalid key type:" + str(type(key))) - def removeOutliers(self): + def removeOutliers(self) -> None: for type, dimMap in self.measurements.items(): for dim, coordMap in dimMap.items(): for coord, values in coordMap.items(): self.measurements[type][dim][coord] = __remove_outliers_using_iqr(values) - def useMedian(self): + def useMedian(self) -> None: for type, dimMap in self.measurements.items(): for dim, coordMap in dimMap.items(): for coord, values in coordMap.items(): self.measurements[type][dim][coord] = [np.median(values).item()] - def useMean(self): + def useMean(self) -> None: for type, dimMap in self.measurements.items(): for dim, coordMap in dimMap.items(): for coord, values in coordMap.items(): self.measurements[type][dim][coord] = [np.mean(values).item()] - def removeZeroParameters(self): + def removeZeroParameters(self) -> None: for type, dimMap in self.measurements.items(): for dim, coordMap in dimMap.items(): for coord in list(coordMap.keys()): diff --git a/discopop_library/discopop_optimizer/OptimizationGraph.py b/discopop_library/discopop_optimizer/OptimizationGraph.py index 2764e2683..26843d8c1 100644 --- a/discopop_library/discopop_optimizer/OptimizationGraph.py +++ b/discopop_library/discopop_optimizer/OptimizationGraph.py @@ -213,7 +213,7 @@ def __init__( # perform actions for headless mode perform_headless_execution(experiment) - def get_next_free_node_id(self): + def get_next_free_node_id(self) -> int: buffer = self.next_free_node_id self.next_free_node_id += 1 return buffer diff --git a/discopop_library/discopop_optimizer/OptimizerArguments.py b/discopop_library/discopop_optimizer/OptimizerArguments.py index 79408bc32..55d79689b 100644 --- a/discopop_library/discopop_optimizer/OptimizerArguments.py +++ b/discopop_library/discopop_optimizer/OptimizerArguments.py @@ -32,10 +32,10 @@ class OptimizerArguments(GeneralArguments): single_suggestions: bool pin_function_calls_to_host: bool - def __post_init__(self): + def __post_init__(self) -> None: self.__validate() - def __validate(self): + def __validate(self) -> None: """Validate the arguments passed to the discopop_optimizer, e.g check if given files exist""" if self.doall_microbench_file != "None": if not os.path.isfile(self.doall_microbench_file): diff --git a/discopop_library/discopop_optimizer/PETParser/PETParser.py b/discopop_library/discopop_optimizer/PETParser/PETParser.py index b7540bb9a..8c37b3d17 100644 --- a/discopop_library/discopop_optimizer/PETParser/PETParser.py +++ b/discopop_library/discopop_optimizer/PETParser/PETParser.py @@ -173,7 +173,7 @@ def get_new_node_id(self) -> int: self.next_free_node_id += 1 return buffer - def __pin_function_calls_to_host(self): + def __pin_function_calls_to_host(self) -> None: host_device_id = self.experiment.get_system().get_host_device_id() logger.info("Pinning functions and function calls to host device: " + str(host_device_id)) for node in get_all_function_nodes(self.graph): @@ -188,7 +188,7 @@ def __pin_function_calls_to_host(self): logger.info("\tPinning calling node: " + str(node)) data_at(self.graph, node).device_id = host_device_id - def __add_calling_edges(self): + def __add_calling_edges(self) -> None: all_function_nodes = get_all_function_nodes(self.graph) for node in self.graph.nodes: @@ -206,7 +206,7 @@ def __add_calling_edges(self): if data_at(self.graph, function).original_cu_id == out_call_edge[1]: add_call_edge(self.graph, node, function) - def __prune_branches(self): + def __prune_branches(self) -> None: """Prune branches based on the measured likelihood of execution""" # check if branch information exists. If not, skip this step. if self.experiment.arguments.pruning_level == 0: @@ -411,7 +411,7 @@ def __identify_most_likely_path(self, node_likelihood_dict: Dict[int, float], fu return keep_nodes - def __flatten_function_graphs(self): + def __flatten_function_graphs(self) -> None: # TODO: remove deepcopies by storing data independently from the nodes for function in get_all_function_nodes(self.graph): @@ -625,7 +625,7 @@ def __fix_too_many_predecessors(self, node: int) -> Tuple[bool, List[int]]: retval = True return retval, list(set(modified_nodes)) - def __remove_non_hotspot_function_bodys(self): + def __remove_non_hotspot_function_bodys(self) -> None: if len(self.experiment.hotspot_functions) == 0: return all_hotspot_functions_raw: List[Tuple[int, str]] = [] @@ -663,7 +663,7 @@ def __remove_non_hotspot_function_bodys(self): self.graph.remove_node(node) # leave the function node - def __remove_invalid_functions(self): + def __remove_invalid_functions(self) -> None: for function in self.invalid_functions: if self.experiment.arguments.verbose: print("Removing body of invalid function: ", cast(FunctionRoot, data_at(self.graph, function)).name) @@ -697,7 +697,7 @@ def __remove_invalid_functions(self): # # if self.experiment.arguments.verbose: # # print("ADDED DUMMY CONNECTION: ", node, function_return_nodes[parent_func]) - def __add_function_return_node(self): + def __add_function_return_node(self) -> None: """Add a return node to each function as a location to force data updates""" for function in get_all_function_nodes(self.graph): queue = get_children(self.graph, function) @@ -732,7 +732,7 @@ def __add_function_return_node(self): else: queue += [s for s in successors if s not in queue] - def __add_branch_return_node(self): + def __add_branch_return_node(self) -> None: """makes sure every branching section has a merge node""" path_return_nodes: Dict[List[int], int] = dict() @@ -750,7 +750,7 @@ def __add_branch_return_node(self): add_successor_edge(self.graph, node, path_return_nodes[path_entry]) print("ADDED EDGE: ", node, "->", path_return_nodes[path_entry]) - def __new_parse_branched_sections(self): + def __new_parse_branched_sections(self) -> None: """Branched sections in the CU Graph are represented by a serialized version in the MOG. To make this possible, Context Snapshot, Restore and Merge points are added to allow a synchronization 'between' the different branches""" @@ -984,11 +984,11 @@ def __get_merge_nodes( ) -> Dict[int, Optional[int]]: """Calculates and returns the merge nodes for paths starting a the given node""" - def get_merge_nodes(node_list, initial_post_dominators=None): - candidates = initial_post_dominators + def get_merge_nodes(node_list: Set[int], initial_post_dominators: Optional[Set[int]] = None) -> Set[int]: + candidates: Set[int] = initial_post_dominators if initial_post_dominators is not None else set() for node in node_list: for succ in get_successors(self.graph, node): - if candidates is None: + if len(candidates) == 0: candidates = post_dominators[succ] candidates = candidates.intersection(post_dominators[succ]) modification_found = True @@ -1009,7 +1009,7 @@ def get_merge_nodes(node_list, initial_post_dominators=None): merge_nodes: Dict[int, Optional[int]] = dict() for node in path_splits: # cleanup candidates to get the earliest merge - candidates = get_merge_nodes([node], post_dominators[node]) + candidates = get_merge_nodes({node}, post_dominators[node]) while len(candidates) > 1: candidates = get_merge_nodes(candidates) @@ -1055,7 +1055,7 @@ def __get_post_dominators(self, node_list: List[int]) -> Dict[int, Set[int]]: modified = new_modified return post_dominators - def __parse_branched_sections(self): + def __parse_branched_sections(self) -> None: """Branched sections in the CU Graph are represented by a serialized version in the MOG. To make this possible, Context Snapshot, Restore and Merge points are added to allow a synchronization 'between' the different branches""" @@ -1182,7 +1182,7 @@ def __parse_branching_point( return duplicate_node_id, context_snapshot_pop_id - def __add_cu_nodes(self): + def __add_cu_nodes(self) -> None: """adds Workload nodes which represent the CU Nodes to the graph. The added nodes will not be connected in any way.""" for cu_node in self.pet.all_nodes(CUNode): @@ -1211,7 +1211,7 @@ def __add_cu_nodes(self): ), ) - def __add_loop_nodes(self): + def __add_loop_nodes(self) -> None: """adds Loop Nodes to the graph. connects contained nodes using Children edges""" for loop_node in self.pet.all_nodes(LoopNode): @@ -1300,7 +1300,7 @@ def __add_loop_nodes(self): # redirect accesses to the cu_id of the entry node to the newly created loop node self.cu_id_to_graph_node_id[entry_node_cu_id] = new_node_id - def __add_functions(self): + def __add_functions(self) -> None: """parse function nodes in the PET graph. Results in the creation of a forest of function graphs.""" for function_node in self.pet.all_nodes(FunctionNode): @@ -1324,7 +1324,7 @@ def __add_functions(self): # save ID self.cu_id_to_graph_node_id[function_node.id] = new_node_id - def __add_pet_successor_edges(self): + def __add_pet_successor_edges(self) -> None: for cu_node in self.pet.all_nodes(CUNode): for successor_cu_id in [t for s, t, d in self.pet.out_edges(cu_node.id, EdgeType.SUCCESSOR)]: add_successor_edge( @@ -1333,11 +1333,11 @@ def __add_pet_successor_edges(self): self.cu_id_to_graph_node_id[successor_cu_id], ) - def __mark_branch_affiliation(self): + def __mark_branch_affiliation(self) -> None: """Mark each nodes' branch affiliation to allow a simple check for 'on same branch' relation without considering the successor relation.""" - def mark_branched_section(node, branch_stack): + def mark_branched_section(node: int, branch_stack: List[int]) -> None: node_data = data_at(self.graph, node) if isinstance(node_data, ContextSnapshot): branch_stack.append(node) @@ -1372,11 +1372,13 @@ def mark_branched_section(node, branch_stack): # for function in get_all_function_nodes(self.graph): # logger.info("calculate data flow for function: " + data_at(self.graph, function).name) - def __calculate_data_flow(self): + def __calculate_data_flow(self) -> None: self.in_data_flow = dict() self.out_data_flow = dict() - def inlined_data_flow_calculation(current_node, current_last_writes): + def inlined_data_flow_calculation( + current_node: Optional[int], current_last_writes: Dict[MemoryRegion, int] + ) -> Dict[MemoryRegion, int]: # TODO add entering and exiting data frames to support resetting at end of a child section while current_node is not None: # check if current_node uses written data @@ -1463,7 +1465,7 @@ def inlined_data_flow_calculation(current_node, current_last_writes): if not self.graph.has_edge(key, entry): add_dataflow_edge(self.graph, key, entry) - def __propagate_reads_and_writes(self): + def __propagate_reads_and_writes(self) -> None: # initialize queue queue = [n for n in self.graph.nodes] @@ -1476,7 +1478,7 @@ def __propagate_reads_and_writes(self): data_at(self.graph, p).written_memory_regions.update(current_data.written_memory_regions) data_at(self.graph, p).read_memory_regions.update(current_data.read_memory_regions) - def __inline_reads_and_writes_from_call(self): + def __inline_reads_and_writes_from_call(self) -> None: for node in self.graph.nodes: called = get_out_call_edges(self.graph, node) if len(called) == 0: diff --git a/discopop_library/discopop_optimizer/UpdateOptimization/RemoveDuplicatedUpdates.py b/discopop_library/discopop_optimizer/UpdateOptimization/RemoveDuplicatedUpdates.py index f5434e5d0..82043b2f3 100644 --- a/discopop_library/discopop_optimizer/UpdateOptimization/RemoveDuplicatedUpdates.py +++ b/discopop_library/discopop_optimizer/UpdateOptimization/RemoveDuplicatedUpdates.py @@ -7,7 +7,7 @@ # directory for details. import logging -from typing import List +from typing import List, Tuple from discopop_library.discopop_optimizer.OptimizerArguments import OptimizerArguments from discopop_library.discopop_optimizer.classes.context.Update import Update from discopop_library.result_classes.OptimizerOutputPattern import OptimizerOutputPattern @@ -21,7 +21,7 @@ def remove_duplicated_updates( cleaned_updates: List[Update] = [] buffer: List[str] = [] - def get_buffer_str(updt, ignore_first_update=False): + def get_buffer_str(updt: Update, ignore_first_update: bool = False) -> str: if ignore_first_update: result_str = "" else: @@ -74,7 +74,7 @@ def get_buffer_str(updt, ignore_first_update=False): pass configuration.data_movement = cleaned_updates - def get_delete_copy_from_buffer_str(updt): + def get_delete_copy_from_buffer_str(updt: Update) -> Tuple[str, bool]: result_str = "C" if updt.copy_delete_data else "" return ( result_str diff --git a/discopop_library/discopop_optimizer/Variables/Experiment.py b/discopop_library/discopop_optimizer/Variables/Experiment.py index cefdb33c3..85c66e166 100644 --- a/discopop_library/discopop_optimizer/Variables/Experiment.py +++ b/discopop_library/discopop_optimizer/Variables/Experiment.py @@ -137,7 +137,7 @@ def register_free_symbol(self, symbol: Symbol, value_suggestion: Optional[Expr] if value_suggestion is not None: self.suggested_values[symbol] = value_suggestion - def get_next_free_node_id(self): + def get_next_free_node_id(self) -> int: buffer = self.next_free_node_id self.next_free_node_id += 1 return buffer diff --git a/discopop_library/discopop_optimizer/Variables/ExperimentUtils.py b/discopop_library/discopop_optimizer/Variables/ExperimentUtils.py index 4e144c728..94e13657b 100644 --- a/discopop_library/discopop_optimizer/Variables/ExperimentUtils.py +++ b/discopop_library/discopop_optimizer/Variables/ExperimentUtils.py @@ -82,7 +82,7 @@ def show_function_models( # finalize scrollable frame scrollable_frame_widget.finalize(row_count=len(considered_functions), row=0, col=0) - def __on_press(): + def __on_press() -> None: for w in spawned_windows: try: w.destroy() diff --git a/discopop_library/discopop_optimizer/__main__.py b/discopop_library/discopop_optimizer/__main__.py index 4a97fd8bc..734e4b57d 100644 --- a/discopop_library/discopop_optimizer/__main__.py +++ b/discopop_library/discopop_optimizer/__main__.py @@ -92,7 +92,7 @@ def parse_args() -> OptimizerArguments: ) -def main(): +def main() -> None: arguments = parse_args() setup_logger(arguments) diff --git a/discopop_library/discopop_optimizer/classes/context/ContextObject.py b/discopop_library/discopop_optimizer/classes/context/ContextObject.py index 02804ab30..c989a91ea 100644 --- a/discopop_library/discopop_optimizer/classes/context/ContextObject.py +++ b/discopop_library/discopop_optimizer/classes/context/ContextObject.py @@ -43,7 +43,7 @@ def __init__(self, initializing_node_id: int, last_seen_device_ids: Optional[Lis self.snapshot_stack = [] # type: ignore self.save_stack = [] # type: ignore # list of lists of ContextObjects, one list per branching depth - def __str__(self): + def __str__(self) -> str: return str(self.necessary_updates) def calculate_and_perform_necessary_updates( diff --git a/discopop_library/discopop_optimizer/classes/context/Update.py b/discopop_library/discopop_optimizer/classes/context/Update.py index a7f9806e7..779615cdb 100644 --- a/discopop_library/discopop_optimizer/classes/context/Update.py +++ b/discopop_library/discopop_optimizer/classes/context/Update.py @@ -58,7 +58,7 @@ def __init__( self.delete_data = delete_data self.copy_delete_data = copy_delete_data - def __str__(self): + def __str__(self) -> str: result_str = "" result_str += "IssueCopyDelete " if self.copy_delete_data else "" result_str += "IssueDelete " if self.delete_data else "" diff --git a/discopop_library/discopop_optimizer/classes/nodes/GenericNode.py b/discopop_library/discopop_optimizer/classes/nodes/GenericNode.py index 0f77acbdf..5f445e48d 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/GenericNode.py +++ b/discopop_library/discopop_optimizer/classes/nodes/GenericNode.py @@ -94,7 +94,7 @@ def register_child( Does not modify the stored model in self or other.""" raise NotImplementedError("Implementation needs to be provided by derived class: !", type(self)) - def register_successor(self, other, root_node): + def register_successor(self, other: CostModel) -> CostModel: """Registers a successor node for the given model. Does not modify the stored model in self or other.""" raise NotImplementedError("Implementation needs to be provided by derived class: !", type(self)) diff --git a/discopop_library/discopop_optimizer/classes/nodes/Loop.py b/discopop_library/discopop_optimizer/classes/nodes/Loop.py index 783c80167..54e40e34a 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/Loop.py +++ b/discopop_library/discopop_optimizer/classes/nodes/Loop.py @@ -130,7 +130,7 @@ def register_child( cm.path_decisions += other.path_decisions return cm - def register_successor(self, other): + def register_successor(self, other: CostModel) -> CostModel: """Registers a successor node for the given model. Does not modify the stored model in self or other.""" # sequential composition is depicted by simply adding the performance models diff --git a/discopop_library/discopop_optimizer/classes/nodes/Workload.py b/discopop_library/discopop_optimizer/classes/nodes/Workload.py index 31ec9a0fb..4c133e508 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/Workload.py +++ b/discopop_library/discopop_optimizer/classes/nodes/Workload.py @@ -142,7 +142,7 @@ def register_child( # since workloads do not modify their children, the performance model of other is simply added to self. return self.performance_model.parallelizable_plus_combine(other) - def register_successor(self, other): + def register_successor(self, other: CostModel) -> CostModel: """Registers a successor node for the given model. Does not modify the stored model in self or other.""" # sequential composition is depicted by simply adding the performance models diff --git a/discopop_library/discopop_optimizer/classes/system/Network.py b/discopop_library/discopop_optimizer/classes/system/Network.py index 485dd5928..42e4da7eb 100644 --- a/discopop_library/discopop_optimizer/classes/system/Network.py +++ b/discopop_library/discopop_optimizer/classes/system/Network.py @@ -18,7 +18,7 @@ class Network(object): __transfer_speeds: Dict[Tuple[Device, Device], Expr] # (MB/s) __transfer_initialization_costs: Dict[Tuple[Device, Device], Expr] - def __init__(self): + def __init__(self) -> None: self.__host_device = None self.__transfer_speeds = dict() self.__transfer_initialization_costs = dict() diff --git a/discopop_library/discopop_optimizer/classes/types/DataAccessType.py b/discopop_library/discopop_optimizer/classes/types/DataAccessType.py index 5f3b2ff83..f9b3b8b02 100644 --- a/discopop_library/discopop_optimizer/classes/types/DataAccessType.py +++ b/discopop_library/discopop_optimizer/classes/types/DataAccessType.py @@ -15,12 +15,12 @@ class ReadDataAccess(object): var_name: Optional[str] from_call: bool - def __init__(self, memory_region: MemoryRegion, var_name: Optional[str], from_call: bool = False): + def __init__(self, memory_region: MemoryRegion, var_name: Optional[str], from_call: bool = False) -> None: self.memory_region = memory_region self.var_name = var_name self.from_call = from_call - def __str__(self): + def __str__(self) -> str: return_str = "" return_str += "C" if self.from_call else "" return_str += "R(" + self.memory_region + ")" @@ -39,16 +39,16 @@ def __init__(self, memory_region: MemoryRegion, unique_id: int, var_name: Option self.var_name = var_name self.from_call = from_call - def __str__(self): + def __str__(self) -> str: return_str = "" return_str += "C" if self.from_call else "" return_str += "W(" + self.memory_region + "-" + str(self.unique_id) + ", --> " + str(self.var_name) + ")" return return_str - def __hash__(self): + def __hash__(self) -> int: return self.unique_id - def toDict(self): + def toDict(self) -> Dict[str, Any]: result_dict: Dict[str, Any] = {} result_dict["memory_region"] = self.memory_region result_dict["unique_id"] = self.unique_id diff --git a/discopop_library/discopop_optimizer/gui/presentation/OptionTable.py b/discopop_library/discopop_optimizer/gui/presentation/OptionTable.py index 0a642c4c0..e0e544cad 100644 --- a/discopop_library/discopop_optimizer/gui/presentation/OptionTable.py +++ b/discopop_library/discopop_optimizer/gui/presentation/OptionTable.py @@ -210,7 +210,7 @@ def show_options( ) export_code_button.grid(row=0, column=2) - def __update_selection(cm, ctx): + def __update_selection(cm: CostModel, ctx: ContextObject) -> None: experiment.selected_paths_per_function[function_root] = (cm, ctx) experiment.substitutions[cast(Symbol, function_root.sequential_costs)] = ( experiment.selected_paths_per_function[function_root][0].sequential_costs diff --git a/discopop_library/discopop_optimizer/gui/queries/ValueTableQuery.py b/discopop_library/discopop_optimizer/gui/queries/ValueTableQuery.py index 2ca1f1393..e9360c6cf 100644 --- a/discopop_library/discopop_optimizer/gui/queries/ValueTableQuery.py +++ b/discopop_library/discopop_optimizer/gui/queries/ValueTableQuery.py @@ -113,7 +113,7 @@ def validate() -> bool: col.configure(background="red") return ret_val - def onPress(): + def onPress() -> None: if not validate(): return # fetch entries diff --git a/discopop_library/discopop_optimizer/gui/widgets/ScrollableFrame.py b/discopop_library/discopop_optimizer/gui/widgets/ScrollableFrame.py index 6c9ced61a..d92d35454 100644 --- a/discopop_library/discopop_optimizer/gui/widgets/ScrollableFrame.py +++ b/discopop_library/discopop_optimizer/gui/widgets/ScrollableFrame.py @@ -6,7 +6,8 @@ # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. import tkinter as tk -from tkinter import ttk +from tkinter import Tk, ttk +from typing import Union class ScrollableFrameWidget(object): @@ -15,7 +16,7 @@ class ScrollableFrameWidget(object): scrollbar: tk.Scrollbar scrollable_frame: tk.Frame # important - def __init__(self, parent_frame): + def __init__(self, parent_frame: Union[tk.Frame, Tk]) -> None: self.container = ttk.Frame(parent_frame) self.canvas = tk.Canvas(self.container) self.scrollbar = ttk.Scrollbar(self.container, orient="vertical", command=self.canvas.yview) diff --git a/discopop_library/discopop_optimizer/optimization/evolutionary_algorithm.py b/discopop_library/discopop_optimizer/optimization/evolutionary_algorithm.py index bc4dbe250..4cb346fe7 100644 --- a/discopop_library/discopop_optimizer/optimization/evolutionary_algorithm.py +++ b/discopop_library/discopop_optimizer/optimization/evolutionary_algorithm.py @@ -190,7 +190,7 @@ def __initialize_fill_worker( global_available_decisions = available_decisions -def __parallel_get_random_configuration(param_tuple): +def __parallel_get_random_configuration(param_tuple: None) -> List[int]: global global_experiment global global_arguments global global_available_decisions @@ -393,7 +393,7 @@ def __initialize_mutate_worker( global_population = population -def __parallel_mutate(param_tuple): +def __parallel_mutate(param_tuple: None) -> Optional[Tuple[List[int], List[int]]]: global global_experiment global global_arguments global global_population diff --git a/discopop_library/discopop_optimizer/optimization/greedy.py b/discopop_library/discopop_optimizer/optimization/greedy.py index 710c52f4e..52ed6b3f6 100644 --- a/discopop_library/discopop_optimizer/optimization/greedy.py +++ b/discopop_library/discopop_optimizer/optimization/greedy.py @@ -157,7 +157,7 @@ def greedy_search( ) -def __get_dicision_list(decisions_dict): +def __get_dicision_list(decisions_dict: Dict[int, List[List[int]]]) -> List[int]: """Converts a dictionary based description of a configuration into a list of integers""" res_list = [] for function in decisions_dict: diff --git a/discopop_library/discopop_optimizer/scheduling/workload_delta.py b/discopop_library/discopop_optimizer/scheduling/workload_delta.py index c28e6c21b..6853b4480 100644 --- a/discopop_library/discopop_optimizer/scheduling/workload_delta.py +++ b/discopop_library/discopop_optimizer/scheduling/workload_delta.py @@ -38,25 +38,25 @@ class WorkloadStack(object): Any ] # List[Union[List[Any], RegularCosts]] # List of WorkloadStacks or integer tuples (min_wl, max_wl) - def __init__(self): + def __init__(self) -> None: self.stack = [] - def enter_new_branched_section(self): + def enter_new_branched_section(self) -> None: """add a new list to the end of self.stack""" innermost_stack, _ = self.__get_innermost_workload_stack() innermost_stack.append([]) - def exit_branched_section(self): + def exit_branched_section(self) -> None: """aggregate the contained branches""" # do nothing, as the functionality is implemented in aggregate pass - def enter_new_branch(self): + def enter_new_branch(self) -> None: """same behavior as enter_branched_section""" innermost_stack, _ = self.__get_innermost_workload_stack() innermost_stack.append([]) - def exit_branch(self): + def exit_branch(self) -> None: """Accumulates costs of the current branch, i.e. the innermost List""" # get innermost stack innermost_stack, indices = self.__get_innermost_workload_stack() @@ -75,7 +75,7 @@ def exit_branch(self): cur_elem = cur_elem[index] cur_elem[indices[-1]] = BranchCosts((min_wl, max_wl)) - def aggregate(self): + def aggregate(self) -> None: # get innermost stack innermost_stack, indices = self.__get_innermost_workload_stack() min_wl = 0 diff --git a/discopop_library/discopop_optimizer/suggestions/optimizers/loop_collapse.py b/discopop_library/discopop_optimizer/suggestions/optimizers/loop_collapse.py index dd7fcef96..8a820f492 100644 --- a/discopop_library/discopop_optimizer/suggestions/optimizers/loop_collapse.py +++ b/discopop_library/discopop_optimizer/suggestions/optimizers/loop_collapse.py @@ -69,14 +69,14 @@ def collapse_loops(experiment: Experiment) -> nx.DiGraph: return global_graph -def __initialize_worker(graph, experiment): +def __initialize_worker(graph: nx.DiGraph, experiment: Experiment) -> None: global global_graph global global_experiment global_graph = graph global_experiment = experiment -def __collapse_loops_in_function(function_node_id): +def __collapse_loops_in_function(function_node_id: int) -> bool: """Return True, if a modification has been found. Return False otherwise.""" global global_graph global global_experiment diff --git a/discopop_library/discopop_optimizer/utilities/MOGUtilities.py b/discopop_library/discopop_optimizer/utilities/MOGUtilities.py index c17cc47f3..3450f6adc 100644 --- a/discopop_library/discopop_optimizer/utilities/MOGUtilities.py +++ b/discopop_library/discopop_optimizer/utilities/MOGUtilities.py @@ -345,7 +345,7 @@ def show(graph: nx.DiGraph, show_dataflow: bool = True, show_mutex_edges: bool = for idx, node in enumerate(graph.nodes): idx_to_node_dict[idx] = node - def update_annot(ind, node_ids_list): + def update_annot(ind: Any, node_ids_list: Any) -> None: node_idx = ind["ind"][0] node_id = node_ids_list[node_idx] xy = pos[node_id] @@ -355,7 +355,7 @@ def update_annot(ind, node_ids_list): text = data_at(graph, node_id).get_hover_text() annot.set_text(text) - def hover(event): + def hover(event: Any) -> None: vis = annot.get_visible() if event.inaxes == ax: for node_type in node_insertion_sequence: @@ -620,7 +620,7 @@ def __initialize_availability_worker(graph: nx.DiGraph, arguments: OptimizerArgu global_arguments = arguments -def __parallel_get_decisions_from_node_recursive(function_node): +def __parallel_get_decisions_from_node_recursive(function_node: int) -> Tuple[int, List[List[int]]]: global global_graph global global_arguments @@ -662,7 +662,7 @@ def get_decisions_from_node_recursive(node_id: int, prev_decisions: List[int]) - return function_node, get_decisions_from_node_recursive(function_node, []) -def __parallel_get_decisions_from_node(function_node): +def __parallel_get_decisions_from_node(function_node: int) -> Tuple[int, List[List[int]]]: global global_graph global global_arguments diff --git a/discopop_library/discopop_optimizer/utilities/visualization/plotting.py b/discopop_library/discopop_optimizer/utilities/visualization/plotting.py index ddbaf0ec3..77c55922f 100644 --- a/discopop_library/discopop_optimizer/utilities/visualization/plotting.py +++ b/discopop_library/discopop_optimizer/utilities/visualization/plotting.py @@ -23,7 +23,7 @@ from networkx.drawing.nx_pydot import graphviz_layout # type: ignore -def show(graph): +def show(graph: nx.DiGraph) -> None: """Plots the graph :return: @@ -158,7 +158,7 @@ def show(graph): for idx, node in enumerate(graph.nodes): idx_to_node_dict[idx] = node - def update_annot(ind, node_ids_list): + def update_annot(ind: Any, node_ids_list: Any) -> None: node_idx = ind["ind"][0] node_id = node_ids_list[node_idx] xy = pos[node_id] @@ -168,7 +168,7 @@ def update_annot(ind, node_ids_list): text = data_at(graph, node_id).get_hover_text() annot.set_text(text) - def hover(event): + def hover(event: Any) -> None: vis = annot.get_visible() if event.inaxes == ax: for node_type in node_insertion_sequence: diff --git a/discopop_library/discopop_optimizer/utilities/visualization/update_graph.py b/discopop_library/discopop_optimizer/utilities/visualization/update_graph.py index 7e9f5ace2..47c0c01f2 100644 --- a/discopop_library/discopop_optimizer/utilities/visualization/update_graph.py +++ b/discopop_library/discopop_optimizer/utilities/visualization/update_graph.py @@ -175,7 +175,7 @@ def show_update_graph(graph: nx.DiGraph, configuration: OptimizerOutputPattern, for idx, node in enumerate(graph.nodes): idx_to_node_dict[idx] = node - def update_annot(ind, node_ids_list): + def update_annot(ind: Any, node_ids_list: Any) -> None: node_idx = ind["ind"][0] node_id = node_ids_list[node_idx] xy = pos[node_id] @@ -185,7 +185,7 @@ def update_annot(ind, node_ids_list): text = data_at(graph, node_id).get_hover_text() annot.set_text(text) - def hover(event): + def hover(event: Any) -> None: vis = annot.get_visible() if event.inaxes == ax: for node_type in node_insertion_sequence: diff --git a/discopop_library/result_classes/DetectionResult.py b/discopop_library/result_classes/DetectionResult.py index d75cf6c8f..ac8f13bc4 100644 --- a/discopop_library/result_classes/DetectionResult.py +++ b/discopop_library/result_classes/DetectionResult.py @@ -6,7 +6,7 @@ # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. from ast import Dict -from typing import List +from typing import List, cast import jsonpickle # type: ignore @@ -32,7 +32,7 @@ def __init__(self, pet: PEGraphX): self.patterns = PatternStorage() pass - def __str__(self): + def __str__(self) -> str: result_str = "" for v in self.__dict__.values(): if type(v) == PEGraphX: @@ -46,11 +46,11 @@ def __str__(self): result_str += value_str return result_str - def dump_to_pickled_json(self): + def dump_to_pickled_json(self) -> str: """Encodes and returns the entire Object into a pickled json string. The encoded string can be reconstructed into an object by using: jsonpickle.decode(json_str) :return: encoded string """ - return jsonpickle.encode(self) + return cast(str, jsonpickle.encode(self)) diff --git a/discopop_library/result_classes/PatternStorage.py b/discopop_library/result_classes/PatternStorage.py index bf6be1bfc..0a415f72a 100644 --- a/discopop_library/result_classes/PatternStorage.py +++ b/discopop_library/result_classes/PatternStorage.py @@ -27,7 +27,7 @@ class PatternStorage(object): optimizer_output: List[PatternBase] merged_pattern: List[PatternBase] - def __init__(self): + def __init__(self) -> None: self.optimizer_output = [] self.merged_pattern = [] diff --git a/test/end_to_end/do_all/backwards_array_access/src/FileMapping.txt b/test/end_to_end/do_all/backwards_array_access/src/FileMapping.txt new file mode 100644 index 000000000..0e8d2b720 --- /dev/null +++ b/test/end_to_end/do_all/backwards_array_access/src/FileMapping.txt @@ -0,0 +1 @@ +1 /home/lukas/git/discopop/test/end_to_end/do_all/backwards_array_access/src/code.cpp diff --git a/test/end_to_end/do_all/calls/above_nesting_level_3/src/FileMapping.txt b/test/end_to_end/do_all/calls/above_nesting_level_3/src/FileMapping.txt new file mode 100644 index 000000000..ad7424431 --- /dev/null +++ b/test/end_to_end/do_all/calls/above_nesting_level_3/src/FileMapping.txt @@ -0,0 +1 @@ +1 /home/lukas/git/discopop/test/end_to_end/do_all/calls/above_nesting_level_3/src/code.cpp diff --git a/test/end_to_end/do_all/calls/above_nesting_level_3/src/code.ll b/test/end_to_end/do_all/calls/above_nesting_level_3/src/code.ll new file mode 100644 index 000000000..cc7c16cfa --- /dev/null +++ b/test/end_to_end/do_all/calls/above_nesting_level_3/src/code.ll @@ -0,0 +1,855 @@ +; ModuleID = 'code.cpp' +source_filename = "code.cpp" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@_ZZ4mainE1n = internal global i32 4000, align 4, !dbg !0 +@.str = private unnamed_addr constant [8 x i8] c"1:5;1:6\00", align 1 +@.str.1 = private unnamed_addr constant [8 x i8] c"1:5;1:8\00", align 1 +@.str.2 = private unnamed_addr constant [4 x i8] c"tmp\00", align 1 +@.str.3 = private unnamed_addr constant [2 x i8] c"i\00", align 1 +@.str.4 = private unnamed_addr constant [4 x i8] c"sum\00", align 1 +@.str.5 = private unnamed_addr constant [2 x i8] c"n\00", align 1 +@.str.6 = private unnamed_addr constant [10 x i8] c"1:14;1:15\00", align 1 +@.str.7 = private unnamed_addr constant [10 x i8] c"1:14;1:17\00", align 1 +@.str.8 = private unnamed_addr constant [10 x i8] c"1:19;1:20\00", align 1 +@.str.9 = private unnamed_addr constant [10 x i8] c"1:19;1:33\00", align 1 +@.str.10 = private unnamed_addr constant [10 x i8] c"1:22;1:23\00", align 1 +@.str.11 = private unnamed_addr constant [10 x i8] c"1:22;1:31\00", align 1 +@.str.12 = private unnamed_addr constant [10 x i8] c"1:25;1:26\00", align 1 +@.str.13 = private unnamed_addr constant [10 x i8] c"1:25;1:29\00", align 1 +@.str.14 = private unnamed_addr constant [12 x i8] c"_ZZ4mainE1n\00", align 1 +@.str.15 = private unnamed_addr constant [5 x i8] c".str\00", align 1 +@.str.16 = private unnamed_addr constant [7 x i8] c".str.1\00", align 1 +@.str.17 = private unnamed_addr constant [7 x i8] c".str.2\00", align 1 +@.str.18 = private unnamed_addr constant [7 x i8] c".str.3\00", align 1 +@.str.19 = private unnamed_addr constant [7 x i8] c".str.4\00", align 1 +@.str.20 = private unnamed_addr constant [7 x i8] c".str.5\00", align 1 +@.str.21 = private unnamed_addr constant [7 x i8] c".str.6\00", align 1 +@.str.22 = private unnamed_addr constant [7 x i8] c".str.7\00", align 1 +@.str.23 = private unnamed_addr constant [7 x i8] c".str.8\00", align 1 +@.str.24 = private unnamed_addr constant [7 x i8] c".str.9\00", align 1 +@.str.25 = private unnamed_addr constant [8 x i8] c".str.10\00", align 1 +@.str.26 = private unnamed_addr constant [8 x i8] c".str.11\00", align 1 +@.str.27 = private unnamed_addr constant [8 x i8] c".str.12\00", align 1 +@.str.28 = private unnamed_addr constant [7 x i8] c"retval\00", align 1 +@.str.29 = private unnamed_addr constant [5 x i8] c"argc\00", align 1 +@.str.30 = private unnamed_addr constant [5 x i8] c"argv\00", align 1 +@.str.31 = private unnamed_addr constant [2 x i8] c"x\00", align 1 +@.str.32 = private unnamed_addr constant [2 x i8] c"k\00", align 1 +@.str.33 = private unnamed_addr constant [2 x i8] c"j\00", align 1 + +; Function Attrs: noinline nounwind optnone uwtable +define i32 @_Z14allowing_doallPdi(double* %tmp, i32 %i) #0 !dbg !263 { +entry: + call void @__dp_func_entry(i32 16388, i32 0) + %__dp_bb1 = alloca i32, align 4 + store i32 0, i32* %__dp_bb1, align 4 + %__dp_bb = alloca i32, align 4 + store i32 0, i32* %__dp_bb, align 4 + %tmp.addr = alloca double*, align 8 + %0 = ptrtoint double** %tmp.addr to i64 + %i.addr = alloca i32, align 4 + %1 = ptrtoint i32* %i.addr to i64 + %sum = alloca i32, align 4 + %2 = ptrtoint i32* %sum to i64 + %n = alloca i32, align 4 + %3 = ptrtoint i32* %n to i64 + %4 = ptrtoint double** %tmp.addr to i64 + store double* %tmp, double** %tmp.addr, align 8 + call void @llvm.dbg.declare(metadata double** %tmp.addr, metadata !266, metadata !DIExpression()), !dbg !267 + %5 = ptrtoint i32* %i.addr to i64 + store i32 %i, i32* %i.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %i.addr, metadata !268, metadata !DIExpression()), !dbg !269 + call void @llvm.dbg.declare(metadata i32* %sum, metadata !270, metadata !DIExpression()), !dbg !271 + %6 = ptrtoint i32* %sum to i64 + store i32 0, i32* %sum, align 4, !dbg !271 + call void @llvm.dbg.declare(metadata i32* %n, metadata !272, metadata !DIExpression()), !dbg !274 + %7 = ptrtoint i32* %n to i64 + store i32 0, i32* %n, align 4, !dbg !274 + call void @__dp_report_bb(i32 0) + br label %for.cond, !dbg !275 + +for.cond: ; preds = %for.inc, %entry + call void @__dp_loop_entry(i32 16390, i32 0) + %8 = ptrtoint i32* %n to i64 + %9 = load i32, i32* %n, align 4, !dbg !276 + %10 = ptrtoint i32* %i.addr to i64 + %11 = load i32, i32* %i.addr, align 4, !dbg !278 + %cmp = icmp slt i32 %9, %11, !dbg !279 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0), i1 %cmp, i32 1), !dbg !280 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.1, i32 0, i32 0), i1 %cmp, i32 0), !dbg !280 + call void @__dp_report_bb(i32 2) + %12 = load i32, i32* %__dp_bb, align 4 + call void @__dp_report_bb_pair(i32 %12, i32 5) + br i1 %cmp, label %for.body, label %for.end, !dbg !280 + +for.body: ; preds = %for.cond + call void @__dp_loop_incr(i32 1) + %13 = ptrtoint double** %tmp.addr to i64 + %14 = load double*, double** %tmp.addr, align 8, !dbg !281 + %15 = ptrtoint i32* %i.addr to i64 + %16 = load i32, i32* %i.addr, align 4, !dbg !283 + %idxprom = sext i32 %16 to i64, !dbg !281 + %arrayidx = getelementptr inbounds double, double* %14, i64 %idxprom, !dbg !281 + %17 = ptrtoint double* %arrayidx to i64 + call void @__dp_read(i32 16391, i64 %17, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.2, i32 0, i32 0)) + %18 = load double, double* %arrayidx, align 8, !dbg !281 + %conv = fptosi double %18 to i32, !dbg !281 + %19 = ptrtoint i32* %sum to i64 + store i32 %conv, i32* %sum, align 4, !dbg !284 + call void @__dp_report_bb(i32 4) + %20 = load i32, i32* %__dp_bb1, align 4 + call void @__dp_report_bb_pair(i32 %20, i32 8) + store i32 1, i32* %__dp_bb1, align 4 + br label %for.inc, !dbg !285 + +for.inc: ; preds = %for.body + %21 = ptrtoint i32* %n to i64 + %22 = load i32, i32* %n, align 4, !dbg !286 + %inc = add nsw i32 %22, 1, !dbg !286 + %23 = ptrtoint i32* %n to i64 + store i32 %inc, i32* %n, align 4, !dbg !286 + call void @__dp_report_bb(i32 3) + %24 = load i32, i32* %__dp_bb, align 4 + call void @__dp_report_bb_pair(i32 %24, i32 6) + store i32 1, i32* %__dp_bb, align 4 + br label %for.cond, !dbg !287, !llvm.loop !288 + +for.end: ; preds = %for.cond + call void @__dp_loop_exit(i32 16393, i32 0) + %25 = ptrtoint i32* %sum to i64 + %26 = load i32, i32* %sum, align 4, !dbg !290 + call void @__dp_report_bb(i32 1) + %27 = load i32, i32* %__dp_bb1, align 4 + call void @__dp_report_bb_pair(i32 %27, i32 7) + call void @__dp_func_exit(i32 16393, i32 0), !dbg !291 + ret i32 %26, !dbg !291 +} + +; Function Attrs: nounwind readnone speculatable willreturn +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +; Function Attrs: noinline norecurse nounwind optnone uwtable +define i32 @main(i32 %argc, i8** %argv) #2 !dbg !2 { +entry: + call void @__dp_func_entry(i32 16396, i32 1) + %__dp_bb35 = alloca i32, align 4 + store i32 0, i32* %__dp_bb35, align 4 + %__dp_bb34 = alloca i32, align 4 + store i32 0, i32* %__dp_bb34, align 4 + %__dp_bb33 = alloca i32, align 4 + store i32 0, i32* %__dp_bb33, align 4 + %__dp_bb32 = alloca i32, align 4 + store i32 0, i32* %__dp_bb32, align 4 + %__dp_bb31 = alloca i32, align 4 + store i32 0, i32* %__dp_bb31, align 4 + %__dp_bb30 = alloca i32, align 4 + store i32 0, i32* %__dp_bb30, align 4 + %__dp_bb = alloca i32, align 4 + store i32 0, i32* %__dp_bb, align 4 + %retval = alloca i32, align 4 + %0 = ptrtoint i32* %retval to i64 + %argc.addr = alloca i32, align 4 + %1 = ptrtoint i32* %argc.addr to i64 + %argv.addr = alloca i8**, align 8 + %2 = ptrtoint i8*** %argv.addr to i64 + %x = alloca double*, align 8 + %3 = ptrtoint double** %x to i64 + %i = alloca i32, align 4 + %4 = ptrtoint i32* %i to i64 + %k = alloca i32, align 4 + %5 = ptrtoint i32* %k to i64 + %j = alloca i32, align 4 + %6 = ptrtoint i32* %j to i64 + %i7 = alloca i32, align 4 + %7 = ptrtoint i32* %i7 to i64 + %sum = alloca i32, align 4 + %8 = ptrtoint i32* %sum to i64 + %9 = ptrtoint i32* %retval to i64 + store i32 0, i32* %retval, align 4 + %10 = ptrtoint i32* %argc.addr to i64 + store i32 %argc, i32* %argc.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %argc.addr, metadata !292, metadata !DIExpression()), !dbg !293 + %11 = ptrtoint i8*** %argv.addr to i64 + store i8** %argv, i8*** %argv.addr, align 8 + call void @llvm.dbg.declare(metadata i8*** %argv.addr, metadata !294, metadata !DIExpression()), !dbg !295 + call void @llvm.dbg.declare(metadata double** %x, metadata !296, metadata !DIExpression()), !dbg !297 + %12 = ptrtoint i32* @_ZZ4mainE1n to i64 + call void @__dp_read(i32 16398, i64 %12, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.14, i32 0, i32 0)) + %13 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !298 + %conv = sext i32 %13 to i64, !dbg !298 + %mul = mul i64 %conv, 8, !dbg !299 + %call = call noalias i8* @malloc(i64 %mul) #4, !dbg !300 + %14 = ptrtoint i8* %call to i64 + call void @__dp_new(i32 16398, i64 %14, i64 %14, i64 %mul), !dbg !301 + %15 = bitcast i8* %call to double*, !dbg !301 + %16 = ptrtoint double** %x to i64 + store double* %15, double** %x, align 8, !dbg !297 + call void @llvm.dbg.declare(metadata i32* %i, metadata !302, metadata !DIExpression()), !dbg !304 + %17 = ptrtoint i32* %i to i64 + store i32 0, i32* %i, align 4, !dbg !304 + call void @__dp_report_bb(i32 9) + br label %for.cond, !dbg !305 + +for.cond: ; preds = %for.inc, %entry + call void @__dp_loop_entry(i32 16401, i32 1) + %18 = ptrtoint i32* %i to i64 + %19 = load i32, i32* %i, align 4, !dbg !306 + %20 = ptrtoint i32* @_ZZ4mainE1n to i64 + call void @__dp_read(i32 16401, i64 %20, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.14, i32 0, i32 0)) + %21 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !308 + %cmp = icmp slt i32 %19, %21, !dbg !309 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.6, i32 0, i32 0), i1 %cmp, i32 1), !dbg !310 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.7, i32 0, i32 0), i1 %cmp, i32 0), !dbg !310 + call void @__dp_report_bb(i32 11) + %22 = load i32, i32* %__dp_bb, align 4 + call void @__dp_report_bb_pair(i32 %22, i32 24) + br i1 %cmp, label %for.body, label %for.end, !dbg !310 + +for.body: ; preds = %for.cond + call void @__dp_loop_incr(i32 5) + %23 = ptrtoint double** %x to i64 + %24 = load double*, double** %x, align 8, !dbg !311 + %25 = ptrtoint i32* %i to i64 + %26 = load i32, i32* %i, align 4, !dbg !313 + %idxprom = sext i32 %26 to i64, !dbg !311 + %arrayidx = getelementptr inbounds double, double* %24, i64 %idxprom, !dbg !311 + %27 = ptrtoint double* %arrayidx to i64 + call void @__dp_write(i32 16402, i64 %27, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.31, i32 0, i32 0)) + store double 1.000000e+00, double* %arrayidx, align 8, !dbg !314 + call void @__dp_report_bb(i32 13) + %28 = load i32, i32* %__dp_bb, align 4 + call void @__dp_report_bb_pair(i32 %28, i32 26) + br label %for.inc, !dbg !315 + +for.inc: ; preds = %for.body + %29 = ptrtoint i32* %i to i64 + %30 = load i32, i32* %i, align 4, !dbg !316 + %inc = add nsw i32 %30, 1, !dbg !316 + %31 = ptrtoint i32* %i to i64 + store i32 %inc, i32* %i, align 4, !dbg !316 + call void @__dp_report_bb(i32 12) + %32 = load i32, i32* %__dp_bb, align 4 + call void @__dp_report_bb_pair(i32 %32, i32 25) + store i32 1, i32* %__dp_bb, align 4 + br label %for.cond, !dbg !317, !llvm.loop !318 + +for.end: ; preds = %for.cond + call void @__dp_loop_exit(i32 16404, i32 1) + call void @llvm.dbg.declare(metadata i32* %k, metadata !320, metadata !DIExpression()), !dbg !322 + %33 = ptrtoint i32* %k to i64 + store i32 0, i32* %k, align 4, !dbg !322 + call void @__dp_report_bb(i32 10) + br label %for.cond1, !dbg !323 + +for.cond1: ; preds = %for.inc27, %for.end + call void @__dp_loop_entry(i32 16404, i32 2) + %34 = ptrtoint i32* %k to i64 + %35 = load i32, i32* %k, align 4, !dbg !324 + %cmp2 = icmp slt i32 %35, 20, !dbg !326 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.8, i32 0, i32 0), i1 %cmp2, i32 1), !dbg !327 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.9, i32 0, i32 0), i1 %cmp2, i32 0), !dbg !327 + call void @__dp_report_bb(i32 15) + %36 = load i32, i32* %__dp_bb30, align 4 + call void @__dp_report_bb_pair(i32 %36, i32 27) + br i1 %cmp2, label %for.body3, label %for.end29, !dbg !327 + +for.body3: ; preds = %for.cond1 + call void @__dp_loop_incr(i32 2) + call void @llvm.dbg.declare(metadata i32* %j, metadata !328, metadata !DIExpression()), !dbg !331 + %37 = ptrtoint i32* %j to i64 + store i32 0, i32* %j, align 4, !dbg !331 + call void @__dp_report_bb(i32 17) + %38 = load i32, i32* %__dp_bb32, align 4 + call void @__dp_report_bb_pair(i32 %38, i32 31) + br label %for.cond4, !dbg !332 + +for.cond4: ; preds = %for.inc24, %for.body3 + call void @__dp_loop_entry(i32 16405, i32 3) + %39 = ptrtoint i32* %j to i64 + %40 = load i32, i32* %j, align 4, !dbg !333 + %cmp5 = icmp slt i32 %40, 20, !dbg !335 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.10, i32 0, i32 0), i1 %cmp5, i32 1), !dbg !336 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.11, i32 0, i32 0), i1 %cmp5, i32 0), !dbg !336 + call void @__dp_report_bb(i32 19) + store i32 1, i32* %__dp_bb32, align 4 + %41 = load i32, i32* %__dp_bb33, align 4 + call void @__dp_report_bb_pair(i32 %41, i32 33) + br i1 %cmp5, label %for.body6, label %for.end26, !dbg !336 + +for.body6: ; preds = %for.cond4 + call void @__dp_loop_incr(i32 3) + call void @llvm.dbg.declare(metadata i32* %i7, metadata !337, metadata !DIExpression()), !dbg !340 + %42 = ptrtoint i32* %i7 to i64 + store i32 0, i32* %i7, align 4, !dbg !340 + call void @__dp_report_bb(i32 21) + %43 = load i32, i32* %__dp_bb34, align 4 + call void @__dp_report_bb_pair(i32 %43, i32 35) + br label %for.cond8, !dbg !341 + +for.cond8: ; preds = %for.inc21, %for.body6 + call void @__dp_loop_entry(i32 16406, i32 4) + %44 = ptrtoint i32* %i7 to i64 + %45 = load i32, i32* %i7, align 4, !dbg !342 + %46 = ptrtoint i32* @_ZZ4mainE1n to i64 + call void @__dp_read(i32 16406, i64 %46, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.14, i32 0, i32 0)) + %47 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !344 + %div = sdiv i32 %47, 400, !dbg !345 + %cmp9 = icmp slt i32 %45, %div, !dbg !346 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.12, i32 0, i32 0), i1 %cmp9, i32 1), !dbg !347 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.13, i32 0, i32 0), i1 %cmp9, i32 0), !dbg !347 + call void @__dp_report_bb(i32 22) + store i32 1, i32* %__dp_bb34, align 4 + %48 = load i32, i32* %__dp_bb35, align 4 + call void @__dp_report_bb_pair(i32 %48, i32 37) + br i1 %cmp9, label %for.body10, label %for.end23, !dbg !347 + +for.body10: ; preds = %for.cond8 + call void @__dp_loop_incr(i32 4) + call void @llvm.dbg.declare(metadata i32* %sum, metadata !348, metadata !DIExpression()), !dbg !350 + %49 = ptrtoint double** %x to i64 + %50 = load double*, double** %x, align 8, !dbg !351 + %51 = ptrtoint i32* %k to i64 + %52 = load i32, i32* %k, align 4, !dbg !352 + %53 = ptrtoint i32* @_ZZ4mainE1n to i64 + call void @__dp_read(i32 16407, i64 %53, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.14, i32 0, i32 0)) + %54 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !353 + %div11 = sdiv i32 %54, 20, !dbg !354 + %mul12 = mul nsw i32 %52, %div11, !dbg !355 + %idx.ext = sext i32 %mul12 to i64, !dbg !356 + %add.ptr = getelementptr inbounds double, double* %50, i64 %idx.ext, !dbg !356 + %55 = ptrtoint i32* %j to i64 + %56 = load i32, i32* %j, align 4, !dbg !357 + %57 = ptrtoint i32* @_ZZ4mainE1n to i64 + call void @__dp_read(i32 16407, i64 %57, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.14, i32 0, i32 0)) + %58 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !358 + %div13 = sdiv i32 %58, 400, !dbg !359 + %mul14 = mul nsw i32 %56, %div13, !dbg !360 + %idx.ext15 = sext i32 %mul14 to i64, !dbg !361 + %add.ptr16 = getelementptr inbounds double, double* %add.ptr, i64 %idx.ext15, !dbg !361 + %59 = ptrtoint i32* %i7 to i64 + %60 = load i32, i32* %i7, align 4, !dbg !362 + %idx.ext17 = sext i32 %60 to i64, !dbg !363 + %add.ptr18 = getelementptr inbounds double, double* %add.ptr16, i64 %idx.ext17, !dbg !363 + %61 = ptrtoint i32* @_ZZ4mainE1n to i64 + call void @__dp_read(i32 16407, i64 %61, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.14, i32 0, i32 0)) + %62 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !364 + %div19 = sdiv i32 %62, 400, !dbg !365 + %63 = ptrtoint i32* %i7 to i64 + %64 = load i32, i32* %i7, align 4, !dbg !366 + %sub = sub nsw i32 %div19, %64, !dbg !367 + call void @__dp_call(i32 16407), !dbg !368 + %call20 = call i32 @_Z14allowing_doallPdi(double* %add.ptr18, i32 %sub), !dbg !368 + %65 = ptrtoint i32* %sum to i64 + store i32 %call20, i32* %sum, align 4, !dbg !350 + call void @__dp_report_bb(i32 18) + %66 = load i32, i32* %__dp_bb30, align 4 + call void @__dp_report_bb_pair(i32 %66, i32 29) + %67 = load i32, i32* %__dp_bb31, align 4 + call void @__dp_report_bb_pair(i32 %67, i32 30) + store i32 1, i32* %__dp_bb31, align 4 + %68 = load i32, i32* %__dp_bb33, align 4 + call void @__dp_report_bb_pair(i32 %68, i32 32) + %69 = load i32, i32* %__dp_bb35, align 4 + call void @__dp_report_bb_pair(i32 %69, i32 36) + br label %for.inc21, !dbg !369 + +for.inc21: ; preds = %for.body10 + %70 = ptrtoint i32* %i7 to i64 + %71 = load i32, i32* %i7, align 4, !dbg !370 + %inc22 = add nsw i32 %71, 1, !dbg !370 + %72 = ptrtoint i32* %i7 to i64 + store i32 %inc22, i32* %i7, align 4, !dbg !370 + call void @__dp_report_bb(i32 23) + %73 = load i32, i32* %__dp_bb35, align 4 + call void @__dp_report_bb_pair(i32 %73, i32 38) + store i32 1, i32* %__dp_bb35, align 4 + br label %for.cond8, !dbg !371, !llvm.loop !372 + +for.end23: ; preds = %for.cond8 + call void @__dp_loop_exit(i32 16409, i32 4) + br label %for.inc24, !dbg !374 + +for.inc24: ; preds = %for.end23 + %74 = ptrtoint i32* %j to i64 + %75 = load i32, i32* %j, align 4, !dbg !375 + %inc25 = add nsw i32 %75, 1, !dbg !375 + %76 = ptrtoint i32* %j to i64 + store i32 %inc25, i32* %j, align 4, !dbg !375 + call void @__dp_report_bb(i32 20) + %77 = load i32, i32* %__dp_bb33, align 4 + call void @__dp_report_bb_pair(i32 %77, i32 34) + store i32 1, i32* %__dp_bb33, align 4 + br label %for.cond4, !dbg !376, !llvm.loop !377 + +for.end26: ; preds = %for.cond4 + call void @__dp_loop_exit(i32 16410, i32 3) + br label %for.inc27, !dbg !379 + +for.inc27: ; preds = %for.end26 + %78 = ptrtoint i32* %k to i64 + %79 = load i32, i32* %k, align 4, !dbg !380 + %inc28 = add nsw i32 %79, 1, !dbg !380 + %80 = ptrtoint i32* %k to i64 + store i32 %inc28, i32* %k, align 4, !dbg !380 + call void @__dp_report_bb(i32 16) + %81 = load i32, i32* %__dp_bb30, align 4 + call void @__dp_report_bb_pair(i32 %81, i32 28) + store i32 1, i32* %__dp_bb30, align 4 + br label %for.cond1, !dbg !381, !llvm.loop !382 + +for.end29: ; preds = %for.cond1 + call void @__dp_loop_exit(i32 16412, i32 2) + %82 = ptrtoint double** %x to i64 + %83 = load double*, double** %x, align 8, !dbg !384 + %84 = bitcast double* %83 to i8*, !dbg !384 + call void @free(i8* %84) #4, !dbg !385 + %85 = ptrtoint i8* %84 to i64 + call void @__dp_delete(i32 16412, i64 %85), !dbg !386 + call void @__dp_report_bb(i32 14) + call void @__dp_finalize(i32 16413), !dbg !386 + call void @__dp_loop_output(), !dbg !386 + call void @__dp_taken_branch_counter_output(), !dbg !386 + ret i32 0, !dbg !386 +} + +; Function Attrs: nounwind +declare noalias i8* @malloc(i64) #3 + +; Function Attrs: nounwind +declare void @free(i8*) #3 + +declare void @__dp_init(i32, i32, i32) + +declare void @__dp_finalize(i32) + +declare void @__dp_read(i32, i64, i8*) + +declare void @__dp_write(i32, i64, i8*) + +declare void @__dp_alloca(i32, i8*, i64, i64, i64, i64) + +declare void @__dp_new(i32, i64, i64, i64) + +declare void @__dp_delete(i32, i64) + +declare void @__dp_call(i32) + +declare void @__dp_func_entry(i32, i32) + +declare void @__dp_func_exit(i32, i32) + +declare void @__dp_loop_entry(i32, i32) + +declare void @__dp_loop_exit(i32, i32) + +declare void @__dp_incr_taken_branch_counter(i8*, i32, i32) + +declare void @__dp_report_bb(i32) + +declare void @__dp_report_bb_pair(i32, i32) + +declare void @__dp_loop_incr(i32) + +declare void @__dp_loop_output() + +declare void @__dp_taken_branch_counter_output() + +attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind readnone speculatable willreturn } +attributes #2 = { noinline norecurse nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #3 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #4 = { nounwind } + +!llvm.dbg.cu = !{!11} +!llvm.module.flags = !{!258, !259, !260, !261} +!llvm.ident = !{!262} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "n", scope: !2, file: !3, line: 13, type: !6, isLocal: true, isDefinition: true) +!2 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 12, type: !4, scopeLine: 12, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !11, retainedNodes: !12) +!3 = !DIFile(filename: "code.cpp", directory: "/home/lukas/git/discopop/test/end_to_end/do_all/calls/above_nesting_level_3/src") +!4 = !DISubroutineType(types: !5) +!5 = !{!6, !6, !7} +!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!7 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64) +!8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64) +!9 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !10) +!10 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!11 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 11.1.0 (https://github.com/llvm/llvm-project.git 7e99bddfeaab2713a8bb6ca538da25b66e6efc59)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !12, retainedTypes: !13, globals: !16, imports: !17, splitDebugInlining: false, nameTableKind: None) +!12 = !{} +!13 = !{!14} +!14 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !15, size: 64) +!15 = !DIBasicType(name: "double", size: 64, encoding: DW_ATE_float) +!16 = !{!0} +!17 = !{!18, !25, !29, !36, !40, !45, !47, !51, !55, !59, !73, !77, !81, !85, !89, !94, !98, !102, !106, !110, !118, !122, !126, !128, !132, !136, !141, !147, !151, !155, !157, !165, !169, !177, !179, !183, !187, !191, !195, !200, !205, !210, !211, !212, !213, !215, !216, !217, !218, !219, !220, !221, !223, !224, !225, !226, !227, !228, !229, !234, !235, !236, !237, !238, !239, !240, !241, !242, !243, !244, !245, !246, !247, !248, !249, !250, !251, !252, !253, !254, !255, !256, !257} +!18 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !20, file: !24, line: 52) +!19 = !DINamespace(name: "std", scope: null) +!20 = !DISubprogram(name: "abs", scope: !21, file: !21, line: 848, type: !22, flags: DIFlagPrototyped, spFlags: 0) +!21 = !DIFile(filename: "/usr/include/stdlib.h", directory: "") +!22 = !DISubroutineType(types: !23) +!23 = !{!6, !6} +!24 = !DIFile(filename: "/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/bits/std_abs.h", directory: "") +!25 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !26, file: !28, line: 127) +!26 = !DIDerivedType(tag: DW_TAG_typedef, name: "div_t", file: !21, line: 63, baseType: !27) +!27 = !DICompositeType(tag: DW_TAG_structure_type, file: !21, line: 59, flags: DIFlagFwdDecl, identifier: "_ZTS5div_t") +!28 = !DIFile(filename: "/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/cstdlib", directory: "") +!29 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !30, file: !28, line: 128) +!30 = !DIDerivedType(tag: DW_TAG_typedef, name: "ldiv_t", file: !21, line: 71, baseType: !31) +!31 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !21, line: 67, size: 128, flags: DIFlagTypePassByValue, elements: !32, identifier: "_ZTS6ldiv_t") +!32 = !{!33, !35} +!33 = !DIDerivedType(tag: DW_TAG_member, name: "quot", scope: !31, file: !21, line: 69, baseType: !34, size: 64) +!34 = !DIBasicType(name: "long int", size: 64, encoding: DW_ATE_signed) +!35 = !DIDerivedType(tag: DW_TAG_member, name: "rem", scope: !31, file: !21, line: 70, baseType: !34, size: 64, offset: 64) +!36 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !37, file: !28, line: 130) +!37 = !DISubprogram(name: "abort", scope: !21, file: !21, line: 598, type: !38, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) +!38 = !DISubroutineType(types: !39) +!39 = !{null} +!40 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !41, file: !28, line: 134) +!41 = !DISubprogram(name: "atexit", scope: !21, file: !21, line: 602, type: !42, flags: DIFlagPrototyped, spFlags: 0) +!42 = !DISubroutineType(types: !43) +!43 = !{!6, !44} +!44 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !38, size: 64) +!45 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !46, file: !28, line: 137) +!46 = !DISubprogram(name: "at_quick_exit", scope: !21, file: !21, line: 607, type: !42, flags: DIFlagPrototyped, spFlags: 0) +!47 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !48, file: !28, line: 140) +!48 = !DISubprogram(name: "atof", scope: !21, file: !21, line: 102, type: !49, flags: DIFlagPrototyped, spFlags: 0) +!49 = !DISubroutineType(types: !50) +!50 = !{!15, !8} +!51 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !52, file: !28, line: 141) +!52 = !DISubprogram(name: "atoi", scope: !21, file: !21, line: 105, type: !53, flags: DIFlagPrototyped, spFlags: 0) +!53 = !DISubroutineType(types: !54) +!54 = !{!6, !8} +!55 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !56, file: !28, line: 142) +!56 = !DISubprogram(name: "atol", scope: !21, file: !21, line: 108, type: !57, flags: DIFlagPrototyped, spFlags: 0) +!57 = !DISubroutineType(types: !58) +!58 = !{!34, !8} +!59 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !60, file: !28, line: 143) +!60 = !DISubprogram(name: "bsearch", scope: !21, file: !21, line: 828, type: !61, flags: DIFlagPrototyped, spFlags: 0) +!61 = !DISubroutineType(types: !62) +!62 = !{!63, !64, !64, !66, !66, !69} +!63 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) +!64 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !65, size: 64) +!65 = !DIDerivedType(tag: DW_TAG_const_type, baseType: null) +!66 = !DIDerivedType(tag: DW_TAG_typedef, name: "size_t", file: !67, line: 46, baseType: !68) +!67 = !DIFile(filename: "Software/llvm-11.1.0/lib/clang/11.1.0/include/stddef.h", directory: "/home/lukas") +!68 = !DIBasicType(name: "long unsigned int", size: 64, encoding: DW_ATE_unsigned) +!69 = !DIDerivedType(tag: DW_TAG_typedef, name: "__compar_fn_t", file: !21, line: 816, baseType: !70) +!70 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !71, size: 64) +!71 = !DISubroutineType(types: !72) +!72 = !{!6, !64, !64} +!73 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !74, file: !28, line: 144) +!74 = !DISubprogram(name: "calloc", scope: !21, file: !21, line: 543, type: !75, flags: DIFlagPrototyped, spFlags: 0) +!75 = !DISubroutineType(types: !76) +!76 = !{!63, !66, !66} +!77 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !78, file: !28, line: 145) +!78 = !DISubprogram(name: "div", scope: !21, file: !21, line: 860, type: !79, flags: DIFlagPrototyped, spFlags: 0) +!79 = !DISubroutineType(types: !80) +!80 = !{!26, !6, !6} +!81 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !82, file: !28, line: 146) +!82 = !DISubprogram(name: "exit", scope: !21, file: !21, line: 624, type: !83, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) +!83 = !DISubroutineType(types: !84) +!84 = !{null, !6} +!85 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !86, file: !28, line: 147) +!86 = !DISubprogram(name: "free", scope: !21, file: !21, line: 555, type: !87, flags: DIFlagPrototyped, spFlags: 0) +!87 = !DISubroutineType(types: !88) +!88 = !{null, !63} +!89 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !90, file: !28, line: 148) +!90 = !DISubprogram(name: "getenv", scope: !21, file: !21, line: 641, type: !91, flags: DIFlagPrototyped, spFlags: 0) +!91 = !DISubroutineType(types: !92) +!92 = !{!93, !8} +!93 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64) +!94 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !95, file: !28, line: 149) +!95 = !DISubprogram(name: "labs", scope: !21, file: !21, line: 849, type: !96, flags: DIFlagPrototyped, spFlags: 0) +!96 = !DISubroutineType(types: !97) +!97 = !{!34, !34} +!98 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !99, file: !28, line: 150) +!99 = !DISubprogram(name: "ldiv", scope: !21, file: !21, line: 862, type: !100, flags: DIFlagPrototyped, spFlags: 0) +!100 = !DISubroutineType(types: !101) +!101 = !{!30, !34, !34} +!102 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !103, file: !28, line: 151) +!103 = !DISubprogram(name: "malloc", scope: !21, file: !21, line: 540, type: !104, flags: DIFlagPrototyped, spFlags: 0) +!104 = !DISubroutineType(types: !105) +!105 = !{!63, !66} +!106 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !107, file: !28, line: 153) +!107 = !DISubprogram(name: "mblen", scope: !21, file: !21, line: 930, type: !108, flags: DIFlagPrototyped, spFlags: 0) +!108 = !DISubroutineType(types: !109) +!109 = !{!6, !8, !66} +!110 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !111, file: !28, line: 154) +!111 = !DISubprogram(name: "mbstowcs", scope: !21, file: !21, line: 941, type: !112, flags: DIFlagPrototyped, spFlags: 0) +!112 = !DISubroutineType(types: !113) +!113 = !{!66, !114, !117, !66} +!114 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !115) +!115 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !116, size: 64) +!116 = !DIBasicType(name: "wchar_t", size: 32, encoding: DW_ATE_signed) +!117 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !8) +!118 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !119, file: !28, line: 155) +!119 = !DISubprogram(name: "mbtowc", scope: !21, file: !21, line: 933, type: !120, flags: DIFlagPrototyped, spFlags: 0) +!120 = !DISubroutineType(types: !121) +!121 = !{!6, !114, !117, !66} +!122 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !123, file: !28, line: 157) +!123 = !DISubprogram(name: "qsort", scope: !21, file: !21, line: 838, type: !124, flags: DIFlagPrototyped, spFlags: 0) +!124 = !DISubroutineType(types: !125) +!125 = !{null, !63, !66, !66, !69} +!126 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !127, file: !28, line: 160) +!127 = !DISubprogram(name: "quick_exit", scope: !21, file: !21, line: 630, type: !83, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) +!128 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !129, file: !28, line: 163) +!129 = !DISubprogram(name: "rand", scope: !21, file: !21, line: 454, type: !130, flags: DIFlagPrototyped, spFlags: 0) +!130 = !DISubroutineType(types: !131) +!131 = !{!6} +!132 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !133, file: !28, line: 164) +!133 = !DISubprogram(name: "realloc", scope: !21, file: !21, line: 551, type: !134, flags: DIFlagPrototyped, spFlags: 0) +!134 = !DISubroutineType(types: !135) +!135 = !{!63, !63, !66} +!136 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !137, file: !28, line: 165) +!137 = !DISubprogram(name: "srand", scope: !21, file: !21, line: 456, type: !138, flags: DIFlagPrototyped, spFlags: 0) +!138 = !DISubroutineType(types: !139) +!139 = !{null, !140} +!140 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned) +!141 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !142, file: !28, line: 166) +!142 = !DISubprogram(name: "strtod", scope: !21, file: !21, line: 118, type: !143, flags: DIFlagPrototyped, spFlags: 0) +!143 = !DISubroutineType(types: !144) +!144 = !{!15, !117, !145} +!145 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !146) +!146 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !93, size: 64) +!147 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !148, file: !28, line: 167) +!148 = !DISubprogram(name: "strtol", scope: !21, file: !21, line: 177, type: !149, flags: DIFlagPrototyped, spFlags: 0) +!149 = !DISubroutineType(types: !150) +!150 = !{!34, !117, !145, !6} +!151 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !152, file: !28, line: 168) +!152 = !DISubprogram(name: "strtoul", scope: !21, file: !21, line: 181, type: !153, flags: DIFlagPrototyped, spFlags: 0) +!153 = !DISubroutineType(types: !154) +!154 = !{!68, !117, !145, !6} +!155 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !156, file: !28, line: 169) +!156 = !DISubprogram(name: "system", scope: !21, file: !21, line: 791, type: !53, flags: DIFlagPrototyped, spFlags: 0) +!157 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !158, file: !28, line: 171) +!158 = !DISubprogram(name: "wcstombs", scope: !21, file: !21, line: 945, type: !159, flags: DIFlagPrototyped, spFlags: 0) +!159 = !DISubroutineType(types: !160) +!160 = !{!66, !161, !162, !66} +!161 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !93) +!162 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !163) +!163 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !164, size: 64) +!164 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !116) +!165 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !166, file: !28, line: 172) +!166 = !DISubprogram(name: "wctomb", scope: !21, file: !21, line: 937, type: !167, flags: DIFlagPrototyped, spFlags: 0) +!167 = !DISubroutineType(types: !168) +!168 = !{!6, !93, !116} +!169 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !171, file: !28, line: 200) +!170 = !DINamespace(name: "__gnu_cxx", scope: null) +!171 = !DIDerivedType(tag: DW_TAG_typedef, name: "lldiv_t", file: !21, line: 81, baseType: !172) +!172 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !21, line: 77, size: 128, flags: DIFlagTypePassByValue, elements: !173, identifier: "_ZTS7lldiv_t") +!173 = !{!174, !176} +!174 = !DIDerivedType(tag: DW_TAG_member, name: "quot", scope: !172, file: !21, line: 79, baseType: !175, size: 64) +!175 = !DIBasicType(name: "long long int", size: 64, encoding: DW_ATE_signed) +!176 = !DIDerivedType(tag: DW_TAG_member, name: "rem", scope: !172, file: !21, line: 80, baseType: !175, size: 64, offset: 64) +!177 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !178, file: !28, line: 206) +!178 = !DISubprogram(name: "_Exit", scope: !21, file: !21, line: 636, type: !83, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) +!179 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !180, file: !28, line: 210) +!180 = !DISubprogram(name: "llabs", scope: !21, file: !21, line: 852, type: !181, flags: DIFlagPrototyped, spFlags: 0) +!181 = !DISubroutineType(types: !182) +!182 = !{!175, !175} +!183 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !184, file: !28, line: 216) +!184 = !DISubprogram(name: "lldiv", scope: !21, file: !21, line: 866, type: !185, flags: DIFlagPrototyped, spFlags: 0) +!185 = !DISubroutineType(types: !186) +!186 = !{!171, !175, !175} +!187 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !188, file: !28, line: 227) +!188 = !DISubprogram(name: "atoll", scope: !21, file: !21, line: 113, type: !189, flags: DIFlagPrototyped, spFlags: 0) +!189 = !DISubroutineType(types: !190) +!190 = !{!175, !8} +!191 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !192, file: !28, line: 228) +!192 = !DISubprogram(name: "strtoll", scope: !21, file: !21, line: 201, type: !193, flags: DIFlagPrototyped, spFlags: 0) +!193 = !DISubroutineType(types: !194) +!194 = !{!175, !117, !145, !6} +!195 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !196, file: !28, line: 229) +!196 = !DISubprogram(name: "strtoull", scope: !21, file: !21, line: 206, type: !197, flags: DIFlagPrototyped, spFlags: 0) +!197 = !DISubroutineType(types: !198) +!198 = !{!199, !117, !145, !6} +!199 = !DIBasicType(name: "long long unsigned int", size: 64, encoding: DW_ATE_unsigned) +!200 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !201, file: !28, line: 231) +!201 = !DISubprogram(name: "strtof", scope: !21, file: !21, line: 124, type: !202, flags: DIFlagPrototyped, spFlags: 0) +!202 = !DISubroutineType(types: !203) +!203 = !{!204, !117, !145} +!204 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) +!205 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !206, file: !28, line: 232) +!206 = !DISubprogram(name: "strtold", scope: !21, file: !21, line: 127, type: !207, flags: DIFlagPrototyped, spFlags: 0) +!207 = !DISubroutineType(types: !208) +!208 = !{!209, !117, !145} +!209 = !DIBasicType(name: "long double", size: 128, encoding: DW_ATE_float) +!210 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !171, file: !28, line: 240) +!211 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !178, file: !28, line: 242) +!212 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !180, file: !28, line: 244) +!213 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !214, file: !28, line: 245) +!214 = !DISubprogram(name: "div", linkageName: "_ZN9__gnu_cxx3divExx", scope: !170, file: !28, line: 213, type: !185, flags: DIFlagPrototyped, spFlags: 0) +!215 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !184, file: !28, line: 246) +!216 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !188, file: !28, line: 248) +!217 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !201, file: !28, line: 249) +!218 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !192, file: !28, line: 250) +!219 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !196, file: !28, line: 251) +!220 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !206, file: !28, line: 252) +!221 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !37, file: !222, line: 38) +!222 = !DIFile(filename: "/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/stdlib.h", directory: "") +!223 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !41, file: !222, line: 39) +!224 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !82, file: !222, line: 40) +!225 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !46, file: !222, line: 43) +!226 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !127, file: !222, line: 46) +!227 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !26, file: !222, line: 51) +!228 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !30, file: !222, line: 52) +!229 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !230, file: !222, line: 54) +!230 = !DISubprogram(name: "abs", linkageName: "_ZSt3absg", scope: !19, file: !24, line: 103, type: !231, flags: DIFlagPrototyped, spFlags: 0) +!231 = !DISubroutineType(types: !232) +!232 = !{!233, !233} +!233 = !DIBasicType(name: "__float128", size: 128, encoding: DW_ATE_float) +!234 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !48, file: !222, line: 55) +!235 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !52, file: !222, line: 56) +!236 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !56, file: !222, line: 57) +!237 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !60, file: !222, line: 58) +!238 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !74, file: !222, line: 59) +!239 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !214, file: !222, line: 60) +!240 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !86, file: !222, line: 61) +!241 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !90, file: !222, line: 62) +!242 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !95, file: !222, line: 63) +!243 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !99, file: !222, line: 64) +!244 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !103, file: !222, line: 65) +!245 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !107, file: !222, line: 67) +!246 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !111, file: !222, line: 68) +!247 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !119, file: !222, line: 69) +!248 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !123, file: !222, line: 71) +!249 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !129, file: !222, line: 72) +!250 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !133, file: !222, line: 73) +!251 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !137, file: !222, line: 74) +!252 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !142, file: !222, line: 75) +!253 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !148, file: !222, line: 76) +!254 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !152, file: !222, line: 77) +!255 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !156, file: !222, line: 78) +!256 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !158, file: !222, line: 80) +!257 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !166, file: !222, line: 81) +!258 = !{i32 7, !"Dwarf Version", i32 4} +!259 = !{i32 2, !"Debug Info Version", i32 3} +!260 = !{i32 1, !"wchar_size", i32 4} +!261 = !{i32 7, !"PIC Level", i32 2} +!262 = !{!"clang version 11.1.0 (https://github.com/llvm/llvm-project.git 7e99bddfeaab2713a8bb6ca538da25b66e6efc59)"} +!263 = distinct !DISubprogram(name: "allowing_doall", linkageName: "_Z14allowing_doallPdi", scope: !3, file: !3, line: 4, type: !264, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !11, retainedNodes: !12) +!264 = !DISubroutineType(types: !265) +!265 = !{!6, !14, !6} +!266 = !DILocalVariable(name: "tmp", arg: 1, scope: !263, file: !3, line: 4, type: !14) +!267 = !DILocation(line: 4, column: 27, scope: !263) +!268 = !DILocalVariable(name: "i", arg: 2, scope: !263, file: !3, line: 4, type: !6) +!269 = !DILocation(line: 4, column: 38, scope: !263) +!270 = !DILocalVariable(name: "sum", scope: !263, file: !3, line: 5, type: !6) +!271 = !DILocation(line: 5, column: 7, scope: !263) +!272 = !DILocalVariable(name: "n", scope: !273, file: !3, line: 6, type: !6) +!273 = distinct !DILexicalBlock(scope: !263, file: !3, line: 6, column: 3) +!274 = !DILocation(line: 6, column: 12, scope: !273) +!275 = !DILocation(line: 6, column: 8, scope: !273) +!276 = !DILocation(line: 6, column: 19, scope: !277) +!277 = distinct !DILexicalBlock(scope: !273, file: !3, line: 6, column: 3) +!278 = !DILocation(line: 6, column: 23, scope: !277) +!279 = !DILocation(line: 6, column: 21, scope: !277) +!280 = !DILocation(line: 6, column: 3, scope: !273) +!281 = !DILocation(line: 7, column: 11, scope: !282) +!282 = distinct !DILexicalBlock(scope: !277, file: !3, line: 6, column: 31) +!283 = !DILocation(line: 7, column: 15, scope: !282) +!284 = !DILocation(line: 7, column: 9, scope: !282) +!285 = !DILocation(line: 8, column: 3, scope: !282) +!286 = !DILocation(line: 6, column: 27, scope: !277) +!287 = !DILocation(line: 6, column: 3, scope: !277) +!288 = distinct !{!288, !280, !289} +!289 = !DILocation(line: 8, column: 3, scope: !273) +!290 = !DILocation(line: 9, column: 10, scope: !263) +!291 = !DILocation(line: 9, column: 3, scope: !263) +!292 = !DILocalVariable(name: "argc", arg: 1, scope: !2, file: !3, line: 12, type: !6) +!293 = !DILocation(line: 12, column: 14, scope: !2) +!294 = !DILocalVariable(name: "argv", arg: 2, scope: !2, file: !3, line: 12, type: !7) +!295 = !DILocation(line: 12, column: 32, scope: !2) +!296 = !DILocalVariable(name: "x", scope: !2, file: !3, line: 14, type: !14) +!297 = !DILocation(line: 14, column: 11, scope: !2) +!298 = !DILocation(line: 14, column: 32, scope: !2) +!299 = !DILocation(line: 14, column: 34, scope: !2) +!300 = !DILocation(line: 14, column: 25, scope: !2) +!301 = !DILocation(line: 14, column: 15, scope: !2) +!302 = !DILocalVariable(name: "i", scope: !303, file: !3, line: 17, type: !6) +!303 = distinct !DILexicalBlock(scope: !2, file: !3, line: 17, column: 3) +!304 = !DILocation(line: 17, column: 12, scope: !303) +!305 = !DILocation(line: 17, column: 8, scope: !303) +!306 = !DILocation(line: 17, column: 19, scope: !307) +!307 = distinct !DILexicalBlock(scope: !303, file: !3, line: 17, column: 3) +!308 = !DILocation(line: 17, column: 23, scope: !307) +!309 = !DILocation(line: 17, column: 21, scope: !307) +!310 = !DILocation(line: 17, column: 3, scope: !303) +!311 = !DILocation(line: 18, column: 5, scope: !312) +!312 = distinct !DILexicalBlock(scope: !307, file: !3, line: 17, column: 31) +!313 = !DILocation(line: 18, column: 7, scope: !312) +!314 = !DILocation(line: 18, column: 10, scope: !312) +!315 = !DILocation(line: 19, column: 3, scope: !312) +!316 = !DILocation(line: 17, column: 27, scope: !307) +!317 = !DILocation(line: 17, column: 3, scope: !307) +!318 = distinct !{!318, !310, !319} +!319 = !DILocation(line: 19, column: 3, scope: !303) +!320 = !DILocalVariable(name: "k", scope: !321, file: !3, line: 20, type: !6) +!321 = distinct !DILexicalBlock(scope: !2, file: !3, line: 20, column: 3) +!322 = !DILocation(line: 20, column: 12, scope: !321) +!323 = !DILocation(line: 20, column: 8, scope: !321) +!324 = !DILocation(line: 20, column: 19, scope: !325) +!325 = distinct !DILexicalBlock(scope: !321, file: !3, line: 20, column: 3) +!326 = !DILocation(line: 20, column: 21, scope: !325) +!327 = !DILocation(line: 20, column: 3, scope: !321) +!328 = !DILocalVariable(name: "j", scope: !329, file: !3, line: 21, type: !6) +!329 = distinct !DILexicalBlock(scope: !330, file: !3, line: 21, column: 5) +!330 = distinct !DILexicalBlock(scope: !325, file: !3, line: 20, column: 32) +!331 = !DILocation(line: 21, column: 14, scope: !329) +!332 = !DILocation(line: 21, column: 10, scope: !329) +!333 = !DILocation(line: 21, column: 21, scope: !334) +!334 = distinct !DILexicalBlock(scope: !329, file: !3, line: 21, column: 5) +!335 = !DILocation(line: 21, column: 23, scope: !334) +!336 = !DILocation(line: 21, column: 5, scope: !329) +!337 = !DILocalVariable(name: "i", scope: !338, file: !3, line: 22, type: !6) +!338 = distinct !DILexicalBlock(scope: !339, file: !3, line: 22, column: 7) +!339 = distinct !DILexicalBlock(scope: !334, file: !3, line: 21, column: 34) +!340 = !DILocation(line: 22, column: 16, scope: !338) +!341 = !DILocation(line: 22, column: 12, scope: !338) +!342 = !DILocation(line: 22, column: 23, scope: !343) +!343 = distinct !DILexicalBlock(scope: !338, file: !3, line: 22, column: 7) +!344 = !DILocation(line: 22, column: 27, scope: !343) +!345 = !DILocation(line: 22, column: 29, scope: !343) +!346 = !DILocation(line: 22, column: 25, scope: !343) +!347 = !DILocation(line: 22, column: 7, scope: !338) +!348 = !DILocalVariable(name: "sum", scope: !349, file: !3, line: 23, type: !6) +!349 = distinct !DILexicalBlock(scope: !343, file: !3, line: 22, column: 47) +!350 = !DILocation(line: 23, column: 13, scope: !349) +!351 = !DILocation(line: 23, column: 34, scope: !349) +!352 = !DILocation(line: 23, column: 38, scope: !349) +!353 = !DILocation(line: 23, column: 43, scope: !349) +!354 = !DILocation(line: 23, column: 45, scope: !349) +!355 = !DILocation(line: 23, column: 40, scope: !349) +!356 = !DILocation(line: 23, column: 36, scope: !349) +!357 = !DILocation(line: 23, column: 53, scope: !349) +!358 = !DILocation(line: 23, column: 58, scope: !349) +!359 = !DILocation(line: 23, column: 60, scope: !349) +!360 = !DILocation(line: 23, column: 55, scope: !349) +!361 = !DILocation(line: 23, column: 51, scope: !349) +!362 = !DILocation(line: 23, column: 75, scope: !349) +!363 = !DILocation(line: 23, column: 73, scope: !349) +!364 = !DILocation(line: 23, column: 79, scope: !349) +!365 = !DILocation(line: 23, column: 81, scope: !349) +!366 = !DILocation(line: 23, column: 96, scope: !349) +!367 = !DILocation(line: 23, column: 94, scope: !349) +!368 = !DILocation(line: 23, column: 19, scope: !349) +!369 = !DILocation(line: 24, column: 7, scope: !349) +!370 = !DILocation(line: 22, column: 42, scope: !343) +!371 = !DILocation(line: 22, column: 7, scope: !343) +!372 = distinct !{!372, !347, !373} +!373 = !DILocation(line: 24, column: 7, scope: !338) +!374 = !DILocation(line: 25, column: 5, scope: !339) +!375 = !DILocation(line: 21, column: 30, scope: !334) +!376 = !DILocation(line: 21, column: 5, scope: !334) +!377 = distinct !{!377, !336, !378} +!378 = !DILocation(line: 25, column: 5, scope: !329) +!379 = !DILocation(line: 26, column: 3, scope: !330) +!380 = !DILocation(line: 20, column: 28, scope: !325) +!381 = !DILocation(line: 20, column: 3, scope: !325) +!382 = distinct !{!382, !327, !383} +!383 = !DILocation(line: 26, column: 3, scope: !321) +!384 = !DILocation(line: 28, column: 8, scope: !2) +!385 = !DILocation(line: 28, column: 3, scope: !2) +!386 = !DILocation(line: 29, column: 3, scope: !2) diff --git a/test/end_to_end/do_all/calls/allowing/src/FileMapping.txt b/test/end_to_end/do_all/calls/allowing/src/FileMapping.txt new file mode 100644 index 000000000..ee9f5f73c --- /dev/null +++ b/test/end_to_end/do_all/calls/allowing/src/FileMapping.txt @@ -0,0 +1 @@ +1 /home/lukas/git/discopop/test/end_to_end/do_all/calls/allowing/src/code.cpp diff --git a/test/end_to_end/do_all/calls/allowing/src/code.ll b/test/end_to_end/do_all/calls/allowing/src/code.ll new file mode 100644 index 000000000..69bd58872 --- /dev/null +++ b/test/end_to_end/do_all/calls/allowing/src/code.ll @@ -0,0 +1,552 @@ +; ModuleID = 'code.cpp' +source_filename = "code.cpp" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@_ZZ4mainE1n = internal global i32 1000, align 4, !dbg !0 +@.str = private unnamed_addr constant [4 x i8] c"tmp\00", align 1 +@.str.1 = private unnamed_addr constant [2 x i8] c"i\00", align 1 +@.str.2 = private unnamed_addr constant [2 x i8] c"z\00", align 1 +@.str.3 = private unnamed_addr constant [10 x i8] c"1:10;1:11\00", align 1 +@.str.4 = private unnamed_addr constant [10 x i8] c"1:10;1:12\00", align 1 +@.str.5 = private unnamed_addr constant [10 x i8] c"1:10;1:15\00", align 1 +@.str.6 = private unnamed_addr constant [12 x i8] c"_ZZ4mainE1n\00", align 1 +@.str.7 = private unnamed_addr constant [5 x i8] c".str\00", align 1 +@.str.8 = private unnamed_addr constant [7 x i8] c".str.1\00", align 1 +@.str.9 = private unnamed_addr constant [7 x i8] c".str.2\00", align 1 +@.str.10 = private unnamed_addr constant [7 x i8] c".str.3\00", align 1 +@.str.11 = private unnamed_addr constant [7 x i8] c".str.4\00", align 1 +@.str.12 = private unnamed_addr constant [7 x i8] c"retval\00", align 1 +@.str.13 = private unnamed_addr constant [5 x i8] c"argc\00", align 1 +@.str.14 = private unnamed_addr constant [5 x i8] c"argv\00", align 1 +@.str.15 = private unnamed_addr constant [2 x i8] c"x\00", align 1 + +; Function Attrs: noinline nounwind optnone uwtable +define void @_Z14allowing_doallPdi(double* %tmp, i32 %i) #0 !dbg !263 { +entry: + call void @__dp_func_entry(i32 16388, i32 0) + %tmp.addr = alloca double*, align 8 + %0 = ptrtoint double** %tmp.addr to i64 + %i.addr = alloca i32, align 4 + %1 = ptrtoint i32* %i.addr to i64 + %z = alloca i32, align 4 + %2 = ptrtoint i32* %z to i64 + %3 = ptrtoint double** %tmp.addr to i64 + store double* %tmp, double** %tmp.addr, align 8 + call void @llvm.dbg.declare(metadata double** %tmp.addr, metadata !266, metadata !DIExpression()), !dbg !267 + %4 = ptrtoint i32* %i.addr to i64 + store i32 %i, i32* %i.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %i.addr, metadata !268, metadata !DIExpression()), !dbg !269 + call void @llvm.dbg.declare(metadata i32* %z, metadata !270, metadata !DIExpression()), !dbg !271 + %5 = ptrtoint i32* %i.addr to i64 + %6 = load i32, i32* %i.addr, align 4, !dbg !272 + %conv = sitofp i32 %6 to double, !dbg !272 + %7 = ptrtoint double** %tmp.addr to i64 + %8 = load double*, double** %tmp.addr, align 8, !dbg !273 + %9 = ptrtoint i32* %i.addr to i64 + %10 = load i32, i32* %i.addr, align 4, !dbg !274 + %idxprom = sext i32 %10 to i64, !dbg !273 + %arrayidx = getelementptr inbounds double, double* %8, i64 %idxprom, !dbg !273 + %11 = ptrtoint double* %arrayidx to i64 + call void @__dp_read(i32 16389, i64 %11, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0)) + %12 = load double, double* %arrayidx, align 8, !dbg !273 + %add = fadd double %conv, %12, !dbg !275 + %conv1 = fptosi double %add to i32, !dbg !272 + %13 = ptrtoint i32* %z to i64 + store i32 %conv1, i32* %z, align 4, !dbg !271 + %14 = ptrtoint i32* %z to i64 + %15 = load i32, i32* %z, align 4, !dbg !276 + %add2 = add nsw i32 %15, 2, !dbg !277 + %conv3 = sitofp i32 %add2 to double, !dbg !276 + %16 = ptrtoint double** %tmp.addr to i64 + %17 = load double*, double** %tmp.addr, align 8, !dbg !278 + %18 = ptrtoint i32* %i.addr to i64 + %19 = load i32, i32* %i.addr, align 4, !dbg !279 + %idxprom4 = sext i32 %19 to i64, !dbg !278 + %arrayidx5 = getelementptr inbounds double, double* %17, i64 %idxprom4, !dbg !278 + %20 = ptrtoint double* %arrayidx5 to i64 + call void @__dp_write(i32 16390, i64 %20, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0)) + store double %conv3, double* %arrayidx5, align 8, !dbg !280 + call void @__dp_report_bb(i32 0) + call void @__dp_func_exit(i32 16391, i32 0), !dbg !281 + ret void, !dbg !281 +} + +; Function Attrs: nounwind readnone speculatable willreturn +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +; Function Attrs: noinline norecurse nounwind optnone uwtable +define i32 @main(i32 %argc, i8** %argv) #2 !dbg !2 { +entry: + call void @__dp_func_entry(i32 16393, i32 1) + %__dp_bb = alloca i32, align 4 + store i32 0, i32* %__dp_bb, align 4 + %retval = alloca i32, align 4 + %0 = ptrtoint i32* %retval to i64 + %argc.addr = alloca i32, align 4 + %1 = ptrtoint i32* %argc.addr to i64 + %argv.addr = alloca i8**, align 8 + %2 = ptrtoint i8*** %argv.addr to i64 + %x = alloca double*, align 8 + %3 = ptrtoint double** %x to i64 + %i = alloca i32, align 4 + %4 = ptrtoint i32* %i to i64 + %5 = ptrtoint i32* %retval to i64 + store i32 0, i32* %retval, align 4 + %6 = ptrtoint i32* %argc.addr to i64 + store i32 %argc, i32* %argc.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %argc.addr, metadata !282, metadata !DIExpression()), !dbg !283 + %7 = ptrtoint i8*** %argv.addr to i64 + store i8** %argv, i8*** %argv.addr, align 8 + call void @llvm.dbg.declare(metadata i8*** %argv.addr, metadata !284, metadata !DIExpression()), !dbg !285 + call void @llvm.dbg.declare(metadata double** %x, metadata !286, metadata !DIExpression()), !dbg !287 + %8 = ptrtoint i32* @_ZZ4mainE1n to i64 + call void @__dp_read(i32 16395, i64 %8, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.6, i32 0, i32 0)) + %9 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !288 + %conv = sext i32 %9 to i64, !dbg !288 + %mul = mul i64 %conv, 8, !dbg !289 + %call = call noalias i8* @malloc(i64 %mul) #4, !dbg !290 + %10 = ptrtoint i8* %call to i64 + call void @__dp_new(i32 16395, i64 %10, i64 %10, i64 %mul), !dbg !291 + %11 = bitcast i8* %call to double*, !dbg !291 + %12 = ptrtoint double** %x to i64 + store double* %11, double** %x, align 8, !dbg !287 + call void @llvm.dbg.declare(metadata i32* %i, metadata !292, metadata !DIExpression()), !dbg !294 + %13 = ptrtoint i32* %i to i64 + store i32 0, i32* %i, align 4, !dbg !294 + call void @__dp_report_bb(i32 1) + br label %for.cond, !dbg !295 + +for.cond: ; preds = %for.inc, %entry + call void @__dp_loop_entry(i32 16398, i32 0) + %14 = ptrtoint i32* %i to i64 + %15 = load i32, i32* %i, align 4, !dbg !296 + %16 = ptrtoint i32* @_ZZ4mainE1n to i64 + call void @__dp_read(i32 16398, i64 %16, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.6, i32 0, i32 0)) + %17 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !298 + %cmp = icmp slt i32 %15, %17, !dbg !299 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.3, i32 0, i32 0), i1 %cmp, i32 1), !dbg !300 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.4, i32 0, i32 0), i1 %cmp, i32 1), !dbg !300 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.5, i32 0, i32 0), i1 %cmp, i32 0), !dbg !300 + call void @__dp_report_bb(i32 3) + %18 = load i32, i32* %__dp_bb, align 4 + call void @__dp_report_bb_pair(i32 %18, i32 6) + br i1 %cmp, label %for.body, label %for.end, !dbg !300 + +for.body: ; preds = %for.cond + call void @__dp_loop_incr(i32 1) + %19 = ptrtoint double** %x to i64 + %20 = load double*, double** %x, align 8, !dbg !301 + %21 = ptrtoint i32* %i to i64 + %22 = load i32, i32* %i, align 4, !dbg !303 + %idxprom = sext i32 %22 to i64, !dbg !301 + %arrayidx = getelementptr inbounds double, double* %20, i64 %idxprom, !dbg !301 + %23 = ptrtoint double* %arrayidx to i64 + call void @__dp_write(i32 16399, i64 %23, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.15, i32 0, i32 0)) + store double 1.000000e+00, double* %arrayidx, align 8, !dbg !304 + %24 = ptrtoint double** %x to i64 + %25 = load double*, double** %x, align 8, !dbg !305 + %26 = ptrtoint i32* %i to i64 + %27 = load i32, i32* %i, align 4, !dbg !306 + call void @__dp_call(i32 16400), !dbg !307 + call void @_Z14allowing_doallPdi(double* %25, i32 %27), !dbg !307 + call void @__dp_report_bb(i32 5) + %28 = load i32, i32* %__dp_bb, align 4 + call void @__dp_report_bb_pair(i32 %28, i32 8) + br label %for.inc, !dbg !308 + +for.inc: ; preds = %for.body + %29 = ptrtoint i32* %i to i64 + %30 = load i32, i32* %i, align 4, !dbg !309 + %inc = add nsw i32 %30, 1, !dbg !309 + %31 = ptrtoint i32* %i to i64 + store i32 %inc, i32* %i, align 4, !dbg !309 + call void @__dp_report_bb(i32 4) + %32 = load i32, i32* %__dp_bb, align 4 + call void @__dp_report_bb_pair(i32 %32, i32 7) + store i32 1, i32* %__dp_bb, align 4 + br label %for.cond, !dbg !310, !llvm.loop !311 + +for.end: ; preds = %for.cond + call void @__dp_loop_exit(i32 16402, i32 0) + %33 = ptrtoint double** %x to i64 + %34 = load double*, double** %x, align 8, !dbg !313 + %35 = bitcast double* %34 to i8*, !dbg !313 + call void @free(i8* %35) #4, !dbg !314 + %36 = ptrtoint i8* %35 to i64 + call void @__dp_delete(i32 16402, i64 %36), !dbg !315 + call void @__dp_report_bb(i32 2) + call void @__dp_finalize(i32 16403), !dbg !315 + call void @__dp_loop_output(), !dbg !315 + call void @__dp_taken_branch_counter_output(), !dbg !315 + ret i32 0, !dbg !315 +} + +; Function Attrs: nounwind +declare noalias i8* @malloc(i64) #3 + +; Function Attrs: nounwind +declare void @free(i8*) #3 + +declare void @__dp_init(i32, i32, i32) + +declare void @__dp_finalize(i32) + +declare void @__dp_read(i32, i64, i8*) + +declare void @__dp_write(i32, i64, i8*) + +declare void @__dp_alloca(i32, i8*, i64, i64, i64, i64) + +declare void @__dp_new(i32, i64, i64, i64) + +declare void @__dp_delete(i32, i64) + +declare void @__dp_call(i32) + +declare void @__dp_func_entry(i32, i32) + +declare void @__dp_func_exit(i32, i32) + +declare void @__dp_loop_entry(i32, i32) + +declare void @__dp_loop_exit(i32, i32) + +declare void @__dp_incr_taken_branch_counter(i8*, i32, i32) + +declare void @__dp_report_bb(i32) + +declare void @__dp_report_bb_pair(i32, i32) + +declare void @__dp_loop_incr(i32) + +declare void @__dp_loop_output() + +declare void @__dp_taken_branch_counter_output() + +attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind readnone speculatable willreturn } +attributes #2 = { noinline norecurse nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #3 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #4 = { nounwind } + +!llvm.dbg.cu = !{!11} +!llvm.module.flags = !{!258, !259, !260, !261} +!llvm.ident = !{!262} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "n", scope: !2, file: !3, line: 10, type: !6, isLocal: true, isDefinition: true) +!2 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 9, type: !4, scopeLine: 9, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !11, retainedNodes: !12) +!3 = !DIFile(filename: "code.cpp", directory: "/home/lukas/git/discopop/test/end_to_end/do_all/calls/allowing/src") +!4 = !DISubroutineType(types: !5) +!5 = !{!6, !6, !7} +!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!7 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64) +!8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64) +!9 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !10) +!10 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!11 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 11.1.0 (https://github.com/llvm/llvm-project.git 7e99bddfeaab2713a8bb6ca538da25b66e6efc59)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !12, retainedTypes: !13, globals: !16, imports: !17, splitDebugInlining: false, nameTableKind: None) +!12 = !{} +!13 = !{!14} +!14 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !15, size: 64) +!15 = !DIBasicType(name: "double", size: 64, encoding: DW_ATE_float) +!16 = !{!0} +!17 = !{!18, !25, !29, !36, !40, !45, !47, !51, !55, !59, !73, !77, !81, !85, !89, !94, !98, !102, !106, !110, !118, !122, !126, !128, !132, !136, !141, !147, !151, !155, !157, !165, !169, !177, !179, !183, !187, !191, !195, !200, !205, !210, !211, !212, !213, !215, !216, !217, !218, !219, !220, !221, !223, !224, !225, !226, !227, !228, !229, !234, !235, !236, !237, !238, !239, !240, !241, !242, !243, !244, !245, !246, !247, !248, !249, !250, !251, !252, !253, !254, !255, !256, !257} +!18 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !20, file: !24, line: 52) +!19 = !DINamespace(name: "std", scope: null) +!20 = !DISubprogram(name: "abs", scope: !21, file: !21, line: 848, type: !22, flags: DIFlagPrototyped, spFlags: 0) +!21 = !DIFile(filename: "/usr/include/stdlib.h", directory: "") +!22 = !DISubroutineType(types: !23) +!23 = !{!6, !6} +!24 = !DIFile(filename: "/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/bits/std_abs.h", directory: "") +!25 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !26, file: !28, line: 127) +!26 = !DIDerivedType(tag: DW_TAG_typedef, name: "div_t", file: !21, line: 63, baseType: !27) +!27 = !DICompositeType(tag: DW_TAG_structure_type, file: !21, line: 59, flags: DIFlagFwdDecl, identifier: "_ZTS5div_t") +!28 = !DIFile(filename: "/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/cstdlib", directory: "") +!29 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !30, file: !28, line: 128) +!30 = !DIDerivedType(tag: DW_TAG_typedef, name: "ldiv_t", file: !21, line: 71, baseType: !31) +!31 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !21, line: 67, size: 128, flags: DIFlagTypePassByValue, elements: !32, identifier: "_ZTS6ldiv_t") +!32 = !{!33, !35} +!33 = !DIDerivedType(tag: DW_TAG_member, name: "quot", scope: !31, file: !21, line: 69, baseType: !34, size: 64) +!34 = !DIBasicType(name: "long int", size: 64, encoding: DW_ATE_signed) +!35 = !DIDerivedType(tag: DW_TAG_member, name: "rem", scope: !31, file: !21, line: 70, baseType: !34, size: 64, offset: 64) +!36 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !37, file: !28, line: 130) +!37 = !DISubprogram(name: "abort", scope: !21, file: !21, line: 598, type: !38, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) +!38 = !DISubroutineType(types: !39) +!39 = !{null} +!40 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !41, file: !28, line: 134) +!41 = !DISubprogram(name: "atexit", scope: !21, file: !21, line: 602, type: !42, flags: DIFlagPrototyped, spFlags: 0) +!42 = !DISubroutineType(types: !43) +!43 = !{!6, !44} +!44 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !38, size: 64) +!45 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !46, file: !28, line: 137) +!46 = !DISubprogram(name: "at_quick_exit", scope: !21, file: !21, line: 607, type: !42, flags: DIFlagPrototyped, spFlags: 0) +!47 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !48, file: !28, line: 140) +!48 = !DISubprogram(name: "atof", scope: !21, file: !21, line: 102, type: !49, flags: DIFlagPrototyped, spFlags: 0) +!49 = !DISubroutineType(types: !50) +!50 = !{!15, !8} +!51 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !52, file: !28, line: 141) +!52 = !DISubprogram(name: "atoi", scope: !21, file: !21, line: 105, type: !53, flags: DIFlagPrototyped, spFlags: 0) +!53 = !DISubroutineType(types: !54) +!54 = !{!6, !8} +!55 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !56, file: !28, line: 142) +!56 = !DISubprogram(name: "atol", scope: !21, file: !21, line: 108, type: !57, flags: DIFlagPrototyped, spFlags: 0) +!57 = !DISubroutineType(types: !58) +!58 = !{!34, !8} +!59 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !60, file: !28, line: 143) +!60 = !DISubprogram(name: "bsearch", scope: !21, file: !21, line: 828, type: !61, flags: DIFlagPrototyped, spFlags: 0) +!61 = !DISubroutineType(types: !62) +!62 = !{!63, !64, !64, !66, !66, !69} +!63 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) +!64 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !65, size: 64) +!65 = !DIDerivedType(tag: DW_TAG_const_type, baseType: null) +!66 = !DIDerivedType(tag: DW_TAG_typedef, name: "size_t", file: !67, line: 46, baseType: !68) +!67 = !DIFile(filename: "Software/llvm-11.1.0/lib/clang/11.1.0/include/stddef.h", directory: "/home/lukas") +!68 = !DIBasicType(name: "long unsigned int", size: 64, encoding: DW_ATE_unsigned) +!69 = !DIDerivedType(tag: DW_TAG_typedef, name: "__compar_fn_t", file: !21, line: 816, baseType: !70) +!70 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !71, size: 64) +!71 = !DISubroutineType(types: !72) +!72 = !{!6, !64, !64} +!73 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !74, file: !28, line: 144) +!74 = !DISubprogram(name: "calloc", scope: !21, file: !21, line: 543, type: !75, flags: DIFlagPrototyped, spFlags: 0) +!75 = !DISubroutineType(types: !76) +!76 = !{!63, !66, !66} +!77 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !78, file: !28, line: 145) +!78 = !DISubprogram(name: "div", scope: !21, file: !21, line: 860, type: !79, flags: DIFlagPrototyped, spFlags: 0) +!79 = !DISubroutineType(types: !80) +!80 = !{!26, !6, !6} +!81 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !82, file: !28, line: 146) +!82 = !DISubprogram(name: "exit", scope: !21, file: !21, line: 624, type: !83, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) +!83 = !DISubroutineType(types: !84) +!84 = !{null, !6} +!85 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !86, file: !28, line: 147) +!86 = !DISubprogram(name: "free", scope: !21, file: !21, line: 555, type: !87, flags: DIFlagPrototyped, spFlags: 0) +!87 = !DISubroutineType(types: !88) +!88 = !{null, !63} +!89 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !90, file: !28, line: 148) +!90 = !DISubprogram(name: "getenv", scope: !21, file: !21, line: 641, type: !91, flags: DIFlagPrototyped, spFlags: 0) +!91 = !DISubroutineType(types: !92) +!92 = !{!93, !8} +!93 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64) +!94 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !95, file: !28, line: 149) +!95 = !DISubprogram(name: "labs", scope: !21, file: !21, line: 849, type: !96, flags: DIFlagPrototyped, spFlags: 0) +!96 = !DISubroutineType(types: !97) +!97 = !{!34, !34} +!98 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !99, file: !28, line: 150) +!99 = !DISubprogram(name: "ldiv", scope: !21, file: !21, line: 862, type: !100, flags: DIFlagPrototyped, spFlags: 0) +!100 = !DISubroutineType(types: !101) +!101 = !{!30, !34, !34} +!102 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !103, file: !28, line: 151) +!103 = !DISubprogram(name: "malloc", scope: !21, file: !21, line: 540, type: !104, flags: DIFlagPrototyped, spFlags: 0) +!104 = !DISubroutineType(types: !105) +!105 = !{!63, !66} +!106 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !107, file: !28, line: 153) +!107 = !DISubprogram(name: "mblen", scope: !21, file: !21, line: 930, type: !108, flags: DIFlagPrototyped, spFlags: 0) +!108 = !DISubroutineType(types: !109) +!109 = !{!6, !8, !66} +!110 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !111, file: !28, line: 154) +!111 = !DISubprogram(name: "mbstowcs", scope: !21, file: !21, line: 941, type: !112, flags: DIFlagPrototyped, spFlags: 0) +!112 = !DISubroutineType(types: !113) +!113 = !{!66, !114, !117, !66} +!114 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !115) +!115 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !116, size: 64) +!116 = !DIBasicType(name: "wchar_t", size: 32, encoding: DW_ATE_signed) +!117 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !8) +!118 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !119, file: !28, line: 155) +!119 = !DISubprogram(name: "mbtowc", scope: !21, file: !21, line: 933, type: !120, flags: DIFlagPrototyped, spFlags: 0) +!120 = !DISubroutineType(types: !121) +!121 = !{!6, !114, !117, !66} +!122 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !123, file: !28, line: 157) +!123 = !DISubprogram(name: "qsort", scope: !21, file: !21, line: 838, type: !124, flags: DIFlagPrototyped, spFlags: 0) +!124 = !DISubroutineType(types: !125) +!125 = !{null, !63, !66, !66, !69} +!126 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !127, file: !28, line: 160) +!127 = !DISubprogram(name: "quick_exit", scope: !21, file: !21, line: 630, type: !83, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) +!128 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !129, file: !28, line: 163) +!129 = !DISubprogram(name: "rand", scope: !21, file: !21, line: 454, type: !130, flags: DIFlagPrototyped, spFlags: 0) +!130 = !DISubroutineType(types: !131) +!131 = !{!6} +!132 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !133, file: !28, line: 164) +!133 = !DISubprogram(name: "realloc", scope: !21, file: !21, line: 551, type: !134, flags: DIFlagPrototyped, spFlags: 0) +!134 = !DISubroutineType(types: !135) +!135 = !{!63, !63, !66} +!136 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !137, file: !28, line: 165) +!137 = !DISubprogram(name: "srand", scope: !21, file: !21, line: 456, type: !138, flags: DIFlagPrototyped, spFlags: 0) +!138 = !DISubroutineType(types: !139) +!139 = !{null, !140} +!140 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned) +!141 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !142, file: !28, line: 166) +!142 = !DISubprogram(name: "strtod", scope: !21, file: !21, line: 118, type: !143, flags: DIFlagPrototyped, spFlags: 0) +!143 = !DISubroutineType(types: !144) +!144 = !{!15, !117, !145} +!145 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !146) +!146 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !93, size: 64) +!147 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !148, file: !28, line: 167) +!148 = !DISubprogram(name: "strtol", scope: !21, file: !21, line: 177, type: !149, flags: DIFlagPrototyped, spFlags: 0) +!149 = !DISubroutineType(types: !150) +!150 = !{!34, !117, !145, !6} +!151 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !152, file: !28, line: 168) +!152 = !DISubprogram(name: "strtoul", scope: !21, file: !21, line: 181, type: !153, flags: DIFlagPrototyped, spFlags: 0) +!153 = !DISubroutineType(types: !154) +!154 = !{!68, !117, !145, !6} +!155 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !156, file: !28, line: 169) +!156 = !DISubprogram(name: "system", scope: !21, file: !21, line: 791, type: !53, flags: DIFlagPrototyped, spFlags: 0) +!157 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !158, file: !28, line: 171) +!158 = !DISubprogram(name: "wcstombs", scope: !21, file: !21, line: 945, type: !159, flags: DIFlagPrototyped, spFlags: 0) +!159 = !DISubroutineType(types: !160) +!160 = !{!66, !161, !162, !66} +!161 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !93) +!162 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !163) +!163 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !164, size: 64) +!164 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !116) +!165 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !166, file: !28, line: 172) +!166 = !DISubprogram(name: "wctomb", scope: !21, file: !21, line: 937, type: !167, flags: DIFlagPrototyped, spFlags: 0) +!167 = !DISubroutineType(types: !168) +!168 = !{!6, !93, !116} +!169 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !171, file: !28, line: 200) +!170 = !DINamespace(name: "__gnu_cxx", scope: null) +!171 = !DIDerivedType(tag: DW_TAG_typedef, name: "lldiv_t", file: !21, line: 81, baseType: !172) +!172 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !21, line: 77, size: 128, flags: DIFlagTypePassByValue, elements: !173, identifier: "_ZTS7lldiv_t") +!173 = !{!174, !176} +!174 = !DIDerivedType(tag: DW_TAG_member, name: "quot", scope: !172, file: !21, line: 79, baseType: !175, size: 64) +!175 = !DIBasicType(name: "long long int", size: 64, encoding: DW_ATE_signed) +!176 = !DIDerivedType(tag: DW_TAG_member, name: "rem", scope: !172, file: !21, line: 80, baseType: !175, size: 64, offset: 64) +!177 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !178, file: !28, line: 206) +!178 = !DISubprogram(name: "_Exit", scope: !21, file: !21, line: 636, type: !83, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) +!179 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !180, file: !28, line: 210) +!180 = !DISubprogram(name: "llabs", scope: !21, file: !21, line: 852, type: !181, flags: DIFlagPrototyped, spFlags: 0) +!181 = !DISubroutineType(types: !182) +!182 = !{!175, !175} +!183 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !184, file: !28, line: 216) +!184 = !DISubprogram(name: "lldiv", scope: !21, file: !21, line: 866, type: !185, flags: DIFlagPrototyped, spFlags: 0) +!185 = !DISubroutineType(types: !186) +!186 = !{!171, !175, !175} +!187 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !188, file: !28, line: 227) +!188 = !DISubprogram(name: "atoll", scope: !21, file: !21, line: 113, type: !189, flags: DIFlagPrototyped, spFlags: 0) +!189 = !DISubroutineType(types: !190) +!190 = !{!175, !8} +!191 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !192, file: !28, line: 228) +!192 = !DISubprogram(name: "strtoll", scope: !21, file: !21, line: 201, type: !193, flags: DIFlagPrototyped, spFlags: 0) +!193 = !DISubroutineType(types: !194) +!194 = !{!175, !117, !145, !6} +!195 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !196, file: !28, line: 229) +!196 = !DISubprogram(name: "strtoull", scope: !21, file: !21, line: 206, type: !197, flags: DIFlagPrototyped, spFlags: 0) +!197 = !DISubroutineType(types: !198) +!198 = !{!199, !117, !145, !6} +!199 = !DIBasicType(name: "long long unsigned int", size: 64, encoding: DW_ATE_unsigned) +!200 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !201, file: !28, line: 231) +!201 = !DISubprogram(name: "strtof", scope: !21, file: !21, line: 124, type: !202, flags: DIFlagPrototyped, spFlags: 0) +!202 = !DISubroutineType(types: !203) +!203 = !{!204, !117, !145} +!204 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) +!205 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !206, file: !28, line: 232) +!206 = !DISubprogram(name: "strtold", scope: !21, file: !21, line: 127, type: !207, flags: DIFlagPrototyped, spFlags: 0) +!207 = !DISubroutineType(types: !208) +!208 = !{!209, !117, !145} +!209 = !DIBasicType(name: "long double", size: 128, encoding: DW_ATE_float) +!210 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !171, file: !28, line: 240) +!211 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !178, file: !28, line: 242) +!212 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !180, file: !28, line: 244) +!213 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !214, file: !28, line: 245) +!214 = !DISubprogram(name: "div", linkageName: "_ZN9__gnu_cxx3divExx", scope: !170, file: !28, line: 213, type: !185, flags: DIFlagPrototyped, spFlags: 0) +!215 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !184, file: !28, line: 246) +!216 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !188, file: !28, line: 248) +!217 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !201, file: !28, line: 249) +!218 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !192, file: !28, line: 250) +!219 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !196, file: !28, line: 251) +!220 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !206, file: !28, line: 252) +!221 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !37, file: !222, line: 38) +!222 = !DIFile(filename: "/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/stdlib.h", directory: "") +!223 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !41, file: !222, line: 39) +!224 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !82, file: !222, line: 40) +!225 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !46, file: !222, line: 43) +!226 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !127, file: !222, line: 46) +!227 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !26, file: !222, line: 51) +!228 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !30, file: !222, line: 52) +!229 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !230, file: !222, line: 54) +!230 = !DISubprogram(name: "abs", linkageName: "_ZSt3absg", scope: !19, file: !24, line: 103, type: !231, flags: DIFlagPrototyped, spFlags: 0) +!231 = !DISubroutineType(types: !232) +!232 = !{!233, !233} +!233 = !DIBasicType(name: "__float128", size: 128, encoding: DW_ATE_float) +!234 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !48, file: !222, line: 55) +!235 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !52, file: !222, line: 56) +!236 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !56, file: !222, line: 57) +!237 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !60, file: !222, line: 58) +!238 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !74, file: !222, line: 59) +!239 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !214, file: !222, line: 60) +!240 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !86, file: !222, line: 61) +!241 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !90, file: !222, line: 62) +!242 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !95, file: !222, line: 63) +!243 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !99, file: !222, line: 64) +!244 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !103, file: !222, line: 65) +!245 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !107, file: !222, line: 67) +!246 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !111, file: !222, line: 68) +!247 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !119, file: !222, line: 69) +!248 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !123, file: !222, line: 71) +!249 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !129, file: !222, line: 72) +!250 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !133, file: !222, line: 73) +!251 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !137, file: !222, line: 74) +!252 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !142, file: !222, line: 75) +!253 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !148, file: !222, line: 76) +!254 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !152, file: !222, line: 77) +!255 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !156, file: !222, line: 78) +!256 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !158, file: !222, line: 80) +!257 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !166, file: !222, line: 81) +!258 = !{i32 7, !"Dwarf Version", i32 4} +!259 = !{i32 2, !"Debug Info Version", i32 3} +!260 = !{i32 1, !"wchar_size", i32 4} +!261 = !{i32 7, !"PIC Level", i32 2} +!262 = !{!"clang version 11.1.0 (https://github.com/llvm/llvm-project.git 7e99bddfeaab2713a8bb6ca538da25b66e6efc59)"} +!263 = distinct !DISubprogram(name: "allowing_doall", linkageName: "_Z14allowing_doallPdi", scope: !3, file: !3, line: 4, type: !264, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !11, retainedNodes: !12) +!264 = !DISubroutineType(types: !265) +!265 = !{null, !14, !6} +!266 = !DILocalVariable(name: "tmp", arg: 1, scope: !263, file: !3, line: 4, type: !14) +!267 = !DILocation(line: 4, column: 29, scope: !263) +!268 = !DILocalVariable(name: "i", arg: 2, scope: !263, file: !3, line: 4, type: !6) +!269 = !DILocation(line: 4, column: 38, scope: !263) +!270 = !DILocalVariable(name: "z", scope: !263, file: !3, line: 5, type: !6) +!271 = !DILocation(line: 5, column: 7, scope: !263) +!272 = !DILocation(line: 5, column: 11, scope: !263) +!273 = !DILocation(line: 5, column: 15, scope: !263) +!274 = !DILocation(line: 5, column: 19, scope: !263) +!275 = !DILocation(line: 5, column: 13, scope: !263) +!276 = !DILocation(line: 6, column: 12, scope: !263) +!277 = !DILocation(line: 6, column: 14, scope: !263) +!278 = !DILocation(line: 6, column: 3, scope: !263) +!279 = !DILocation(line: 6, column: 7, scope: !263) +!280 = !DILocation(line: 6, column: 10, scope: !263) +!281 = !DILocation(line: 7, column: 1, scope: !263) +!282 = !DILocalVariable(name: "argc", arg: 1, scope: !2, file: !3, line: 9, type: !6) +!283 = !DILocation(line: 9, column: 14, scope: !2) +!284 = !DILocalVariable(name: "argv", arg: 2, scope: !2, file: !3, line: 9, type: !7) +!285 = !DILocation(line: 9, column: 32, scope: !2) +!286 = !DILocalVariable(name: "x", scope: !2, file: !3, line: 11, type: !14) +!287 = !DILocation(line: 11, column: 11, scope: !2) +!288 = !DILocation(line: 11, column: 32, scope: !2) +!289 = !DILocation(line: 11, column: 34, scope: !2) +!290 = !DILocation(line: 11, column: 25, scope: !2) +!291 = !DILocation(line: 11, column: 15, scope: !2) +!292 = !DILocalVariable(name: "i", scope: !293, file: !3, line: 14, type: !6) +!293 = distinct !DILexicalBlock(scope: !2, file: !3, line: 14, column: 3) +!294 = !DILocation(line: 14, column: 12, scope: !293) +!295 = !DILocation(line: 14, column: 8, scope: !293) +!296 = !DILocation(line: 14, column: 19, scope: !297) +!297 = distinct !DILexicalBlock(scope: !293, file: !3, line: 14, column: 3) +!298 = !DILocation(line: 14, column: 23, scope: !297) +!299 = !DILocation(line: 14, column: 21, scope: !297) +!300 = !DILocation(line: 14, column: 3, scope: !293) +!301 = !DILocation(line: 15, column: 5, scope: !302) +!302 = distinct !DILexicalBlock(scope: !297, file: !3, line: 14, column: 31) +!303 = !DILocation(line: 15, column: 7, scope: !302) +!304 = !DILocation(line: 15, column: 10, scope: !302) +!305 = !DILocation(line: 16, column: 20, scope: !302) +!306 = !DILocation(line: 16, column: 23, scope: !302) +!307 = !DILocation(line: 16, column: 5, scope: !302) +!308 = !DILocation(line: 17, column: 3, scope: !302) +!309 = !DILocation(line: 14, column: 26, scope: !297) +!310 = !DILocation(line: 14, column: 3, scope: !297) +!311 = distinct !{!311, !300, !312} +!312 = !DILocation(line: 17, column: 3, scope: !293) +!313 = !DILocation(line: 18, column: 8, scope: !2) +!314 = !DILocation(line: 18, column: 3, scope: !2) +!315 = !DILocation(line: 19, column: 3, scope: !2) diff --git a/test/end_to_end/do_all/calls/complex/src/FileMapping.txt b/test/end_to_end/do_all/calls/complex/src/FileMapping.txt deleted file mode 100644 index e77368562..000000000 --- a/test/end_to_end/do_all/calls/complex/src/FileMapping.txt +++ /dev/null @@ -1 +0,0 @@ -1 /home/lukas/git/discopop/test/end_to_end/do_all/calls/complex/src/code.cpp diff --git a/test/end_to_end/do_all/calls/complex/src/code.ll b/test/end_to_end/do_all/calls/complex/src/code.ll deleted file mode 100644 index c6ad70045..000000000 --- a/test/end_to_end/do_all/calls/complex/src/code.ll +++ /dev/null @@ -1,780 +0,0 @@ -; ModuleID = 'code.cpp' -source_filename = "code.cpp" -target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-unknown-linux-gnu" - -@_ZZ4mainE1n = internal global i32 5000, align 4, !dbg !0 -@_ZZ4mainE1a = internal global double 2.000000e+00, align 8, !dbg !17 -@.str = private unnamed_addr constant [5 x i8] c"base\00", align 1 -@.str.1 = private unnamed_addr constant [9 x i8] c"offset_1\00", align 1 -@.str.2 = private unnamed_addr constant [9 x i8] c"offset_2\00", align 1 -@.str.3 = private unnamed_addr constant [6 x i8] c"index\00", align 1 -@.str.4 = private unnamed_addr constant [2 x i8] c"n\00", align 1 -@.str.5 = private unnamed_addr constant [10 x i8] c"1:19;1:20\00", align 1 -@.str.6 = private unnamed_addr constant [10 x i8] c"1:19;1:22\00", align 1 -@.str.7 = private unnamed_addr constant [10 x i8] c"1:24;1:25\00", align 1 -@.str.8 = private unnamed_addr constant [10 x i8] c"1:24;1:28\00", align 1 -@.str.9 = private unnamed_addr constant [10 x i8] c"1:30;1:31\00", align 1 -@.str.10 = private unnamed_addr constant [10 x i8] c"1:30;1:34\00", align 1 -@.str.11 = private unnamed_addr constant [12 x i8] c"_ZZ4mainE1n\00", align 1 -@.str.12 = private unnamed_addr constant [12 x i8] c"_ZZ4mainE1a\00", align 1 -@.str.13 = private unnamed_addr constant [5 x i8] c".str\00", align 1 -@.str.14 = private unnamed_addr constant [7 x i8] c".str.1\00", align 1 -@.str.15 = private unnamed_addr constant [7 x i8] c".str.2\00", align 1 -@.str.16 = private unnamed_addr constant [7 x i8] c".str.3\00", align 1 -@.str.17 = private unnamed_addr constant [7 x i8] c".str.4\00", align 1 -@.str.18 = private unnamed_addr constant [7 x i8] c".str.5\00", align 1 -@.str.19 = private unnamed_addr constant [7 x i8] c".str.6\00", align 1 -@.str.20 = private unnamed_addr constant [7 x i8] c".str.7\00", align 1 -@.str.21 = private unnamed_addr constant [7 x i8] c".str.8\00", align 1 -@.str.22 = private unnamed_addr constant [7 x i8] c".str.9\00", align 1 -@.str.23 = private unnamed_addr constant [7 x i8] c"retval\00", align 1 -@.str.24 = private unnamed_addr constant [5 x i8] c"argc\00", align 1 -@.str.25 = private unnamed_addr constant [5 x i8] c"argv\00", align 1 -@.str.26 = private unnamed_addr constant [2 x i8] c"x\00", align 1 -@.str.27 = private unnamed_addr constant [2 x i8] c"i\00", align 1 - -; Function Attrs: noinline nounwind optnone uwtable -define void @_Z19perform_calculationPdii(double* %base, i32 %offset_1, i32 %offset_2) #0 !dbg !265 { -entry: - call void @__dp_func_entry(i32 16388, i32 0) - %base.addr = alloca double*, align 8 - %0 = ptrtoint double** %base.addr to i64 - %offset_1.addr = alloca i32, align 4 - %1 = ptrtoint i32* %offset_1.addr to i64 - %offset_2.addr = alloca i32, align 4 - %2 = ptrtoint i32* %offset_2.addr to i64 - %3 = ptrtoint double** %base.addr to i64 - store double* %base, double** %base.addr, align 8 - call void @llvm.dbg.declare(metadata double** %base.addr, metadata !268, metadata !DIExpression()), !dbg !269 - %4 = ptrtoint i32* %offset_1.addr to i64 - store i32 %offset_1, i32* %offset_1.addr, align 4 - call void @llvm.dbg.declare(metadata i32* %offset_1.addr, metadata !270, metadata !DIExpression()), !dbg !271 - %5 = ptrtoint i32* %offset_2.addr to i64 - store i32 %offset_2, i32* %offset_2.addr, align 4 - call void @llvm.dbg.declare(metadata i32* %offset_2.addr, metadata !272, metadata !DIExpression()), !dbg !273 - %6 = ptrtoint double** %base.addr to i64 - %7 = load double*, double** %base.addr, align 8, !dbg !274 - %8 = ptrtoint i32* %offset_2.addr to i64 - %9 = load i32, i32* %offset_2.addr, align 4, !dbg !275 - %idxprom = sext i32 %9 to i64, !dbg !274 - %arrayidx = getelementptr inbounds double, double* %7, i64 %idxprom, !dbg !274 - %10 = ptrtoint double* %arrayidx to i64 - call void @__dp_read(i32 16388, i64 %10, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i32 0, i32 0)) - %11 = load double, double* %arrayidx, align 8, !dbg !274 - %add = fadd double 4.200000e+01, %11, !dbg !276 - %12 = ptrtoint double** %base.addr to i64 - %13 = load double*, double** %base.addr, align 8, !dbg !277 - %14 = ptrtoint i32* %offset_1.addr to i64 - %15 = load i32, i32* %offset_1.addr, align 4, !dbg !278 - %idxprom1 = sext i32 %15 to i64, !dbg !277 - %arrayidx2 = getelementptr inbounds double, double* %13, i64 %idxprom1, !dbg !277 - %16 = ptrtoint double* %arrayidx2 to i64 - call void @__dp_write(i32 16388, i64 %16, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i32 0, i32 0)) - store double %add, double* %arrayidx2, align 8, !dbg !279 - call void @__dp_report_bb(i32 0) - call void @__dp_func_exit(i32 16388, i32 0), !dbg !280 - ret void, !dbg !280 -} - -; Function Attrs: nounwind readnone speculatable willreturn -declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 - -; Function Attrs: noinline nounwind optnone uwtable -define void @_Z14doall_possiblePdi(double* %base, i32 %index) #0 !dbg !281 { -entry: - call void @__dp_func_entry(i32 16390, i32 0) - %base.addr = alloca double*, align 8 - %0 = ptrtoint double** %base.addr to i64 - %index.addr = alloca i32, align 4 - %1 = ptrtoint i32* %index.addr to i64 - %2 = ptrtoint double** %base.addr to i64 - store double* %base, double** %base.addr, align 8 - call void @llvm.dbg.declare(metadata double** %base.addr, metadata !284, metadata !DIExpression()), !dbg !285 - %3 = ptrtoint i32* %index.addr to i64 - store i32 %index, i32* %index.addr, align 4 - call void @llvm.dbg.declare(metadata i32* %index.addr, metadata !286, metadata !DIExpression()), !dbg !287 - %4 = ptrtoint double** %base.addr to i64 - %5 = load double*, double** %base.addr, align 8, !dbg !288 - %6 = ptrtoint i32* %index.addr to i64 - %7 = load i32, i32* %index.addr, align 4, !dbg !289 - %8 = ptrtoint i32* %index.addr to i64 - %9 = load i32, i32* %index.addr, align 4, !dbg !290 - call void @__dp_call(i32 16390), !dbg !291 - call void @_Z19perform_calculationPdii(double* %5, i32 %7, i32 %9), !dbg !291 - call void @__dp_report_bb(i32 1) - call void @__dp_func_exit(i32 16390, i32 0), !dbg !292 - ret void, !dbg !292 -} - -; Function Attrs: noinline nounwind optnone uwtable -define void @_Z18doall_not_possiblePdii(double* %base, i32 %index, i32 %n) #0 !dbg !293 { -entry: - call void @__dp_func_entry(i32 16392, i32 0) - %base.addr = alloca double*, align 8 - %0 = ptrtoint double** %base.addr to i64 - %index.addr = alloca i32, align 4 - %1 = ptrtoint i32* %index.addr to i64 - %n.addr = alloca i32, align 4 - %2 = ptrtoint i32* %n.addr to i64 - %3 = ptrtoint double** %base.addr to i64 - store double* %base, double** %base.addr, align 8 - call void @llvm.dbg.declare(metadata double** %base.addr, metadata !294, metadata !DIExpression()), !dbg !295 - %4 = ptrtoint i32* %index.addr to i64 - store i32 %index, i32* %index.addr, align 4 - call void @llvm.dbg.declare(metadata i32* %index.addr, metadata !296, metadata !DIExpression()), !dbg !297 - %5 = ptrtoint i32* %n.addr to i64 - store i32 %n, i32* %n.addr, align 4 - call void @llvm.dbg.declare(metadata i32* %n.addr, metadata !298, metadata !DIExpression()), !dbg !299 - %6 = ptrtoint double** %base.addr to i64 - %7 = load double*, double** %base.addr, align 8, !dbg !300 - %8 = ptrtoint i32* %index.addr to i64 - %9 = load i32, i32* %index.addr, align 4, !dbg !301 - %10 = ptrtoint i32* %index.addr to i64 - %11 = load i32, i32* %index.addr, align 4, !dbg !302 - %12 = ptrtoint i32* %n.addr to i64 - %13 = load i32, i32* %n.addr, align 4, !dbg !303 - %rem = srem i32 422, %13, !dbg !304 - %add = add nsw i32 %11, %rem, !dbg !305 - call void @__dp_call(i32 16392), !dbg !306 - call void @_Z19perform_calculationPdii(double* %7, i32 %9, i32 %add), !dbg !306 - call void @__dp_report_bb(i32 2) - call void @__dp_func_exit(i32 16392, i32 0), !dbg !307 - ret void, !dbg !307 -} - -; Function Attrs: noinline norecurse nounwind optnone uwtable -define i32 @main(i32 %argc, i8** %argv) #2 !dbg !2 { -entry: - call void @__dp_func_entry(i32 16394, i32 1) - %__dp_bb16 = alloca i32, align 4 - store i32 0, i32* %__dp_bb16, align 4 - %__dp_bb15 = alloca i32, align 4 - store i32 0, i32* %__dp_bb15, align 4 - %__dp_bb = alloca i32, align 4 - store i32 0, i32* %__dp_bb, align 4 - %retval = alloca i32, align 4 - %0 = ptrtoint i32* %retval to i64 - %argc.addr = alloca i32, align 4 - %1 = ptrtoint i32* %argc.addr to i64 - %argv.addr = alloca i8**, align 8 - %2 = ptrtoint i8*** %argv.addr to i64 - %x = alloca double*, align 8 - %3 = ptrtoint double** %x to i64 - %i = alloca i32, align 4 - %4 = ptrtoint i32* %i to i64 - %i1 = alloca i32, align 4 - %5 = ptrtoint i32* %i1 to i64 - %i8 = alloca i32, align 4 - %6 = ptrtoint i32* %i8 to i64 - %7 = ptrtoint i32* %retval to i64 - store i32 0, i32* %retval, align 4 - %8 = ptrtoint i32* %argc.addr to i64 - store i32 %argc, i32* %argc.addr, align 4 - call void @llvm.dbg.declare(metadata i32* %argc.addr, metadata !308, metadata !DIExpression()), !dbg !309 - %9 = ptrtoint i8*** %argv.addr to i64 - store i8** %argv, i8*** %argv.addr, align 8 - call void @llvm.dbg.declare(metadata i8*** %argv.addr, metadata !310, metadata !DIExpression()), !dbg !311 - call void @llvm.dbg.declare(metadata double** %x, metadata !312, metadata !DIExpression()), !dbg !313 - %10 = ptrtoint i32* @_ZZ4mainE1n to i64 - call void @__dp_read(i32 16397, i64 %10, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.11, i32 0, i32 0)) - %11 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !314 - %conv = sext i32 %11 to i64, !dbg !314 - %mul = mul i64 %conv, 8, !dbg !315 - %call = call noalias i8* @malloc(i64 %mul) #4, !dbg !316 - %12 = ptrtoint i8* %call to i64 - call void @__dp_new(i32 16397, i64 %12, i64 %12, i64 %mul), !dbg !317 - %13 = bitcast i8* %call to double*, !dbg !317 - %14 = ptrtoint double** %x to i64 - store double* %13, double** %x, align 8, !dbg !313 - call void @llvm.dbg.declare(metadata i32* %i, metadata !318, metadata !DIExpression()), !dbg !320 - %15 = ptrtoint i32* %i to i64 - store i32 0, i32* %i, align 4, !dbg !320 - call void @__dp_report_bb(i32 3) - br label %for.cond, !dbg !321 - -for.cond: ; preds = %for.inc, %entry - call void @__dp_loop_entry(i32 16401, i32 0) - %16 = ptrtoint i32* %i to i64 - %17 = load i32, i32* %i, align 4, !dbg !322 - %18 = ptrtoint i32* @_ZZ4mainE1n to i64 - call void @__dp_read(i32 16401, i64 %18, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.11, i32 0, i32 0)) - %19 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !324 - %cmp = icmp slt i32 %17, %19, !dbg !325 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.5, i32 0, i32 0), i1 %cmp, i32 1), !dbg !326 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.6, i32 0, i32 0), i1 %cmp, i32 0), !dbg !326 - call void @__dp_report_bb(i32 4) - %20 = load i32, i32* %__dp_bb, align 4 - call void @__dp_report_bb_pair(i32 %20, i32 16) - br i1 %cmp, label %for.body, label %for.end, !dbg !326 - -for.body: ; preds = %for.cond - call void @__dp_loop_incr(i32 3) - %21 = ptrtoint double** %x to i64 - %22 = load double*, double** %x, align 8, !dbg !327 - %23 = ptrtoint i32* %i to i64 - %24 = load i32, i32* %i, align 4, !dbg !329 - %idxprom = sext i32 %24 to i64, !dbg !327 - %arrayidx = getelementptr inbounds double, double* %22, i64 %idxprom, !dbg !327 - %25 = ptrtoint double* %arrayidx to i64 - call void @__dp_write(i32 16402, i64 %25, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.26, i32 0, i32 0)) - store double 1.000000e+00, double* %arrayidx, align 8, !dbg !330 - call void @__dp_report_bb(i32 7) - %26 = load i32, i32* %__dp_bb, align 4 - call void @__dp_report_bb_pair(i32 %26, i32 18) - br label %for.inc, !dbg !331 - -for.inc: ; preds = %for.body - %27 = ptrtoint i32* %i to i64 - %28 = load i32, i32* %i, align 4, !dbg !332 - %inc = add nsw i32 %28, 1, !dbg !332 - %29 = ptrtoint i32* %i to i64 - store i32 %inc, i32* %i, align 4, !dbg !332 - call void @__dp_report_bb(i32 6) - %30 = load i32, i32* %__dp_bb, align 4 - call void @__dp_report_bb_pair(i32 %30, i32 17) - store i32 1, i32* %__dp_bb, align 4 - br label %for.cond, !dbg !333, !llvm.loop !334 - -for.end: ; preds = %for.cond - call void @__dp_loop_exit(i32 16406, i32 0) - call void @llvm.dbg.declare(metadata i32* %i1, metadata !336, metadata !DIExpression()), !dbg !338 - %31 = ptrtoint i32* %i1 to i64 - store i32 0, i32* %i1, align 4, !dbg !338 - call void @__dp_report_bb(i32 5) - br label %for.cond2, !dbg !339 - -for.cond2: ; preds = %for.inc5, %for.end - call void @__dp_loop_entry(i32 16406, i32 1) - %32 = ptrtoint i32* %i1 to i64 - %33 = load i32, i32* %i1, align 4, !dbg !340 - %34 = ptrtoint i32* @_ZZ4mainE1n to i64 - call void @__dp_read(i32 16406, i64 %34, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.11, i32 0, i32 0)) - %35 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !342 - %cmp3 = icmp slt i32 %33, %35, !dbg !343 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.7, i32 0, i32 0), i1 %cmp3, i32 1), !dbg !344 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.8, i32 0, i32 0), i1 %cmp3, i32 0), !dbg !344 - call void @__dp_report_bb(i32 9) - %36 = load i32, i32* %__dp_bb15, align 4 - call void @__dp_report_bb_pair(i32 %36, i32 19) - br i1 %cmp3, label %for.body4, label %for.end7, !dbg !344 - -for.body4: ; preds = %for.cond2 - call void @__dp_loop_incr(i32 2) - %37 = ptrtoint double** %x to i64 - %38 = load double*, double** %x, align 8, !dbg !345 - %39 = ptrtoint i32* %i1 to i64 - %40 = load i32, i32* %i1, align 4, !dbg !347 - call void @__dp_call(i32 16407), !dbg !348 - call void @_Z14doall_possiblePdi(double* %38, i32 %40), !dbg !348 - call void @__dp_report_bb(i32 11) - %41 = load i32, i32* %__dp_bb15, align 4 - call void @__dp_report_bb_pair(i32 %41, i32 21) - br label %for.inc5, !dbg !349 - -for.inc5: ; preds = %for.body4 - %42 = ptrtoint i32* %i1 to i64 - %43 = load i32, i32* %i1, align 4, !dbg !350 - %inc6 = add nsw i32 %43, 1, !dbg !350 - %44 = ptrtoint i32* %i1 to i64 - store i32 %inc6, i32* %i1, align 4, !dbg !350 - call void @__dp_report_bb(i32 10) - %45 = load i32, i32* %__dp_bb15, align 4 - call void @__dp_report_bb_pair(i32 %45, i32 20) - store i32 1, i32* %__dp_bb15, align 4 - br label %for.cond2, !dbg !351, !llvm.loop !352 - -for.end7: ; preds = %for.cond2 - call void @__dp_loop_exit(i32 16411, i32 1) - call void @llvm.dbg.declare(metadata i32* %i8, metadata !354, metadata !DIExpression()), !dbg !356 - %46 = ptrtoint i32* %i8 to i64 - store i32 0, i32* %i8, align 4, !dbg !356 - call void @__dp_report_bb(i32 8) - br label %for.cond9, !dbg !357 - -for.cond9: ; preds = %for.inc12, %for.end7 - call void @__dp_loop_entry(i32 16411, i32 2) - %47 = ptrtoint i32* %i8 to i64 - %48 = load i32, i32* %i8, align 4, !dbg !358 - %49 = ptrtoint i32* @_ZZ4mainE1n to i64 - call void @__dp_read(i32 16411, i64 %49, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.11, i32 0, i32 0)) - %50 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !360 - %cmp10 = icmp slt i32 %48, %50, !dbg !361 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.9, i32 0, i32 0), i1 %cmp10, i32 1), !dbg !362 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.10, i32 0, i32 0), i1 %cmp10, i32 0), !dbg !362 - call void @__dp_report_bb(i32 13) - %51 = load i32, i32* %__dp_bb16, align 4 - call void @__dp_report_bb_pair(i32 %51, i32 22) - br i1 %cmp10, label %for.body11, label %for.end14, !dbg !362 - -for.body11: ; preds = %for.cond9 - call void @__dp_loop_incr(i32 1) - %52 = ptrtoint double** %x to i64 - %53 = load double*, double** %x, align 8, !dbg !363 - %54 = ptrtoint i32* %i8 to i64 - %55 = load i32, i32* %i8, align 4, !dbg !365 - %56 = ptrtoint i32* @_ZZ4mainE1n to i64 - call void @__dp_read(i32 16412, i64 %56, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.11, i32 0, i32 0)) - %57 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !366 - call void @__dp_call(i32 16412), !dbg !367 - call void @_Z18doall_not_possiblePdii(double* %53, i32 %55, i32 %57), !dbg !367 - call void @__dp_report_bb(i32 15) - %58 = load i32, i32* %__dp_bb16, align 4 - call void @__dp_report_bb_pair(i32 %58, i32 24) - br label %for.inc12, !dbg !368 - -for.inc12: ; preds = %for.body11 - %59 = ptrtoint i32* %i8 to i64 - %60 = load i32, i32* %i8, align 4, !dbg !369 - %inc13 = add nsw i32 %60, 1, !dbg !369 - %61 = ptrtoint i32* %i8 to i64 - store i32 %inc13, i32* %i8, align 4, !dbg !369 - call void @__dp_report_bb(i32 14) - %62 = load i32, i32* %__dp_bb16, align 4 - call void @__dp_report_bb_pair(i32 %62, i32 23) - store i32 1, i32* %__dp_bb16, align 4 - br label %for.cond9, !dbg !370, !llvm.loop !371 - -for.end14: ; preds = %for.cond9 - call void @__dp_loop_exit(i32 16415, i32 2) - %63 = ptrtoint double** %x to i64 - %64 = load double*, double** %x, align 8, !dbg !373 - %65 = bitcast double* %64 to i8*, !dbg !373 - call void @free(i8* %65) #4, !dbg !374 - %66 = ptrtoint i8* %65 to i64 - call void @__dp_delete(i32 16415, i64 %66), !dbg !375 - call void @__dp_report_bb(i32 12) - call void @__dp_finalize(i32 16417), !dbg !375 - call void @__dp_loop_output(), !dbg !375 - call void @__dp_taken_branch_counter_output(), !dbg !375 - ret i32 0, !dbg !375 -} - -; Function Attrs: nounwind -declare noalias i8* @malloc(i64) #3 - -; Function Attrs: nounwind -declare void @free(i8*) #3 - -declare void @__dp_init(i32, i32, i32) - -declare void @__dp_finalize(i32) - -declare void @__dp_read(i32, i64, i8*) - -declare void @__dp_write(i32, i64, i8*) - -declare void @__dp_alloca(i32, i8*, i64, i64, i64, i64) - -declare void @__dp_new(i32, i64, i64, i64) - -declare void @__dp_delete(i32, i64) - -declare void @__dp_call(i32) - -declare void @__dp_func_entry(i32, i32) - -declare void @__dp_func_exit(i32, i32) - -declare void @__dp_loop_entry(i32, i32) - -declare void @__dp_loop_exit(i32, i32) - -declare void @__dp_incr_taken_branch_counter(i8*, i32, i32) - -declare void @__dp_report_bb(i32) - -declare void @__dp_report_bb_pair(i32, i32) - -declare void @__dp_loop_incr(i32) - -declare void @__dp_loop_output() - -declare void @__dp_taken_branch_counter_output() - -attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { nounwind readnone speculatable willreturn } -attributes #2 = { noinline norecurse nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #3 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #4 = { nounwind } - -!llvm.dbg.cu = !{!11} -!llvm.module.flags = !{!260, !261, !262, !263} -!llvm.ident = !{!264} - -!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) -!1 = distinct !DIGlobalVariable(name: "n", scope: !2, file: !3, line: 11, type: !6, isLocal: true, isDefinition: true) -!2 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 10, type: !4, scopeLine: 10, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !11, retainedNodes: !12) -!3 = !DIFile(filename: "code.cpp", directory: "/home/lukas/git/discopop/test/end_to_end/do_all/calls/complex/src") -!4 = !DISubroutineType(types: !5) -!5 = !{!6, !6, !7} -!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) -!7 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64) -!8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64) -!9 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !10) -!10 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) -!11 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 11.1.0 (https://github.com/llvm/llvm-project.git 7e99bddfeaab2713a8bb6ca538da25b66e6efc59)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !12, retainedTypes: !13, globals: !16, imports: !19, splitDebugInlining: false, nameTableKind: None) -!12 = !{} -!13 = !{!14} -!14 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !15, size: 64) -!15 = !DIBasicType(name: "double", size: 64, encoding: DW_ATE_float) -!16 = !{!0, !17} -!17 = !DIGlobalVariableExpression(var: !18, expr: !DIExpression()) -!18 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 12, type: !15, isLocal: true, isDefinition: true) -!19 = !{!20, !27, !31, !38, !42, !47, !49, !53, !57, !61, !75, !79, !83, !87, !91, !96, !100, !104, !108, !112, !120, !124, !128, !130, !134, !138, !143, !149, !153, !157, !159, !167, !171, !179, !181, !185, !189, !193, !197, !202, !207, !212, !213, !214, !215, !217, !218, !219, !220, !221, !222, !223, !225, !226, !227, !228, !229, !230, !231, !236, !237, !238, !239, !240, !241, !242, !243, !244, !245, !246, !247, !248, !249, !250, !251, !252, !253, !254, !255, !256, !257, !258, !259} -!20 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !22, file: !26, line: 52) -!21 = !DINamespace(name: "std", scope: null) -!22 = !DISubprogram(name: "abs", scope: !23, file: !23, line: 848, type: !24, flags: DIFlagPrototyped, spFlags: 0) -!23 = !DIFile(filename: "/usr/include/stdlib.h", directory: "") -!24 = !DISubroutineType(types: !25) -!25 = !{!6, !6} -!26 = !DIFile(filename: "/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/bits/std_abs.h", directory: "") -!27 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !28, file: !30, line: 127) -!28 = !DIDerivedType(tag: DW_TAG_typedef, name: "div_t", file: !23, line: 63, baseType: !29) -!29 = !DICompositeType(tag: DW_TAG_structure_type, file: !23, line: 59, flags: DIFlagFwdDecl, identifier: "_ZTS5div_t") -!30 = !DIFile(filename: "/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/cstdlib", directory: "") -!31 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !32, file: !30, line: 128) -!32 = !DIDerivedType(tag: DW_TAG_typedef, name: "ldiv_t", file: !23, line: 71, baseType: !33) -!33 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !23, line: 67, size: 128, flags: DIFlagTypePassByValue, elements: !34, identifier: "_ZTS6ldiv_t") -!34 = !{!35, !37} -!35 = !DIDerivedType(tag: DW_TAG_member, name: "quot", scope: !33, file: !23, line: 69, baseType: !36, size: 64) -!36 = !DIBasicType(name: "long int", size: 64, encoding: DW_ATE_signed) -!37 = !DIDerivedType(tag: DW_TAG_member, name: "rem", scope: !33, file: !23, line: 70, baseType: !36, size: 64, offset: 64) -!38 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !39, file: !30, line: 130) -!39 = !DISubprogram(name: "abort", scope: !23, file: !23, line: 598, type: !40, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) -!40 = !DISubroutineType(types: !41) -!41 = !{null} -!42 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !43, file: !30, line: 134) -!43 = !DISubprogram(name: "atexit", scope: !23, file: !23, line: 602, type: !44, flags: DIFlagPrototyped, spFlags: 0) -!44 = !DISubroutineType(types: !45) -!45 = !{!6, !46} -!46 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !40, size: 64) -!47 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !48, file: !30, line: 137) -!48 = !DISubprogram(name: "at_quick_exit", scope: !23, file: !23, line: 607, type: !44, flags: DIFlagPrototyped, spFlags: 0) -!49 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !50, file: !30, line: 140) -!50 = !DISubprogram(name: "atof", scope: !23, file: !23, line: 102, type: !51, flags: DIFlagPrototyped, spFlags: 0) -!51 = !DISubroutineType(types: !52) -!52 = !{!15, !8} -!53 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !54, file: !30, line: 141) -!54 = !DISubprogram(name: "atoi", scope: !23, file: !23, line: 105, type: !55, flags: DIFlagPrototyped, spFlags: 0) -!55 = !DISubroutineType(types: !56) -!56 = !{!6, !8} -!57 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !58, file: !30, line: 142) -!58 = !DISubprogram(name: "atol", scope: !23, file: !23, line: 108, type: !59, flags: DIFlagPrototyped, spFlags: 0) -!59 = !DISubroutineType(types: !60) -!60 = !{!36, !8} -!61 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !62, file: !30, line: 143) -!62 = !DISubprogram(name: "bsearch", scope: !23, file: !23, line: 828, type: !63, flags: DIFlagPrototyped, spFlags: 0) -!63 = !DISubroutineType(types: !64) -!64 = !{!65, !66, !66, !68, !68, !71} -!65 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) -!66 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !67, size: 64) -!67 = !DIDerivedType(tag: DW_TAG_const_type, baseType: null) -!68 = !DIDerivedType(tag: DW_TAG_typedef, name: "size_t", file: !69, line: 46, baseType: !70) -!69 = !DIFile(filename: "Software/llvm-11.1.0/lib/clang/11.1.0/include/stddef.h", directory: "/home/lukas") -!70 = !DIBasicType(name: "long unsigned int", size: 64, encoding: DW_ATE_unsigned) -!71 = !DIDerivedType(tag: DW_TAG_typedef, name: "__compar_fn_t", file: !23, line: 816, baseType: !72) -!72 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !73, size: 64) -!73 = !DISubroutineType(types: !74) -!74 = !{!6, !66, !66} -!75 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !76, file: !30, line: 144) -!76 = !DISubprogram(name: "calloc", scope: !23, file: !23, line: 543, type: !77, flags: DIFlagPrototyped, spFlags: 0) -!77 = !DISubroutineType(types: !78) -!78 = !{!65, !68, !68} -!79 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !80, file: !30, line: 145) -!80 = !DISubprogram(name: "div", scope: !23, file: !23, line: 860, type: !81, flags: DIFlagPrototyped, spFlags: 0) -!81 = !DISubroutineType(types: !82) -!82 = !{!28, !6, !6} -!83 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !84, file: !30, line: 146) -!84 = !DISubprogram(name: "exit", scope: !23, file: !23, line: 624, type: !85, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) -!85 = !DISubroutineType(types: !86) -!86 = !{null, !6} -!87 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !88, file: !30, line: 147) -!88 = !DISubprogram(name: "free", scope: !23, file: !23, line: 555, type: !89, flags: DIFlagPrototyped, spFlags: 0) -!89 = !DISubroutineType(types: !90) -!90 = !{null, !65} -!91 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !92, file: !30, line: 148) -!92 = !DISubprogram(name: "getenv", scope: !23, file: !23, line: 641, type: !93, flags: DIFlagPrototyped, spFlags: 0) -!93 = !DISubroutineType(types: !94) -!94 = !{!95, !8} -!95 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64) -!96 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !97, file: !30, line: 149) -!97 = !DISubprogram(name: "labs", scope: !23, file: !23, line: 849, type: !98, flags: DIFlagPrototyped, spFlags: 0) -!98 = !DISubroutineType(types: !99) -!99 = !{!36, !36} -!100 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !101, file: !30, line: 150) -!101 = !DISubprogram(name: "ldiv", scope: !23, file: !23, line: 862, type: !102, flags: DIFlagPrototyped, spFlags: 0) -!102 = !DISubroutineType(types: !103) -!103 = !{!32, !36, !36} -!104 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !105, file: !30, line: 151) -!105 = !DISubprogram(name: "malloc", scope: !23, file: !23, line: 540, type: !106, flags: DIFlagPrototyped, spFlags: 0) -!106 = !DISubroutineType(types: !107) -!107 = !{!65, !68} -!108 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !109, file: !30, line: 153) -!109 = !DISubprogram(name: "mblen", scope: !23, file: !23, line: 930, type: !110, flags: DIFlagPrototyped, spFlags: 0) -!110 = !DISubroutineType(types: !111) -!111 = !{!6, !8, !68} -!112 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !113, file: !30, line: 154) -!113 = !DISubprogram(name: "mbstowcs", scope: !23, file: !23, line: 941, type: !114, flags: DIFlagPrototyped, spFlags: 0) -!114 = !DISubroutineType(types: !115) -!115 = !{!68, !116, !119, !68} -!116 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !117) -!117 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !118, size: 64) -!118 = !DIBasicType(name: "wchar_t", size: 32, encoding: DW_ATE_signed) -!119 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !8) -!120 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !121, file: !30, line: 155) -!121 = !DISubprogram(name: "mbtowc", scope: !23, file: !23, line: 933, type: !122, flags: DIFlagPrototyped, spFlags: 0) -!122 = !DISubroutineType(types: !123) -!123 = !{!6, !116, !119, !68} -!124 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !125, file: !30, line: 157) -!125 = !DISubprogram(name: "qsort", scope: !23, file: !23, line: 838, type: !126, flags: DIFlagPrototyped, spFlags: 0) -!126 = !DISubroutineType(types: !127) -!127 = !{null, !65, !68, !68, !71} -!128 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !129, file: !30, line: 160) -!129 = !DISubprogram(name: "quick_exit", scope: !23, file: !23, line: 630, type: !85, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) -!130 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !131, file: !30, line: 163) -!131 = !DISubprogram(name: "rand", scope: !23, file: !23, line: 454, type: !132, flags: DIFlagPrototyped, spFlags: 0) -!132 = !DISubroutineType(types: !133) -!133 = !{!6} -!134 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !135, file: !30, line: 164) -!135 = !DISubprogram(name: "realloc", scope: !23, file: !23, line: 551, type: !136, flags: DIFlagPrototyped, spFlags: 0) -!136 = !DISubroutineType(types: !137) -!137 = !{!65, !65, !68} -!138 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !139, file: !30, line: 165) -!139 = !DISubprogram(name: "srand", scope: !23, file: !23, line: 456, type: !140, flags: DIFlagPrototyped, spFlags: 0) -!140 = !DISubroutineType(types: !141) -!141 = !{null, !142} -!142 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned) -!143 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !144, file: !30, line: 166) -!144 = !DISubprogram(name: "strtod", scope: !23, file: !23, line: 118, type: !145, flags: DIFlagPrototyped, spFlags: 0) -!145 = !DISubroutineType(types: !146) -!146 = !{!15, !119, !147} -!147 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !148) -!148 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !95, size: 64) -!149 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !150, file: !30, line: 167) -!150 = !DISubprogram(name: "strtol", scope: !23, file: !23, line: 177, type: !151, flags: DIFlagPrototyped, spFlags: 0) -!151 = !DISubroutineType(types: !152) -!152 = !{!36, !119, !147, !6} -!153 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !154, file: !30, line: 168) -!154 = !DISubprogram(name: "strtoul", scope: !23, file: !23, line: 181, type: !155, flags: DIFlagPrototyped, spFlags: 0) -!155 = !DISubroutineType(types: !156) -!156 = !{!70, !119, !147, !6} -!157 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !158, file: !30, line: 169) -!158 = !DISubprogram(name: "system", scope: !23, file: !23, line: 791, type: !55, flags: DIFlagPrototyped, spFlags: 0) -!159 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !160, file: !30, line: 171) -!160 = !DISubprogram(name: "wcstombs", scope: !23, file: !23, line: 945, type: !161, flags: DIFlagPrototyped, spFlags: 0) -!161 = !DISubroutineType(types: !162) -!162 = !{!68, !163, !164, !68} -!163 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !95) -!164 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !165) -!165 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !166, size: 64) -!166 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !118) -!167 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !168, file: !30, line: 172) -!168 = !DISubprogram(name: "wctomb", scope: !23, file: !23, line: 937, type: !169, flags: DIFlagPrototyped, spFlags: 0) -!169 = !DISubroutineType(types: !170) -!170 = !{!6, !95, !118} -!171 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !172, entity: !173, file: !30, line: 200) -!172 = !DINamespace(name: "__gnu_cxx", scope: null) -!173 = !DIDerivedType(tag: DW_TAG_typedef, name: "lldiv_t", file: !23, line: 81, baseType: !174) -!174 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !23, line: 77, size: 128, flags: DIFlagTypePassByValue, elements: !175, identifier: "_ZTS7lldiv_t") -!175 = !{!176, !178} -!176 = !DIDerivedType(tag: DW_TAG_member, name: "quot", scope: !174, file: !23, line: 79, baseType: !177, size: 64) -!177 = !DIBasicType(name: "long long int", size: 64, encoding: DW_ATE_signed) -!178 = !DIDerivedType(tag: DW_TAG_member, name: "rem", scope: !174, file: !23, line: 80, baseType: !177, size: 64, offset: 64) -!179 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !172, entity: !180, file: !30, line: 206) -!180 = !DISubprogram(name: "_Exit", scope: !23, file: !23, line: 636, type: !85, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) -!181 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !172, entity: !182, file: !30, line: 210) -!182 = !DISubprogram(name: "llabs", scope: !23, file: !23, line: 852, type: !183, flags: DIFlagPrototyped, spFlags: 0) -!183 = !DISubroutineType(types: !184) -!184 = !{!177, !177} -!185 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !172, entity: !186, file: !30, line: 216) -!186 = !DISubprogram(name: "lldiv", scope: !23, file: !23, line: 866, type: !187, flags: DIFlagPrototyped, spFlags: 0) -!187 = !DISubroutineType(types: !188) -!188 = !{!173, !177, !177} -!189 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !172, entity: !190, file: !30, line: 227) -!190 = !DISubprogram(name: "atoll", scope: !23, file: !23, line: 113, type: !191, flags: DIFlagPrototyped, spFlags: 0) -!191 = !DISubroutineType(types: !192) -!192 = !{!177, !8} -!193 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !172, entity: !194, file: !30, line: 228) -!194 = !DISubprogram(name: "strtoll", scope: !23, file: !23, line: 201, type: !195, flags: DIFlagPrototyped, spFlags: 0) -!195 = !DISubroutineType(types: !196) -!196 = !{!177, !119, !147, !6} -!197 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !172, entity: !198, file: !30, line: 229) -!198 = !DISubprogram(name: "strtoull", scope: !23, file: !23, line: 206, type: !199, flags: DIFlagPrototyped, spFlags: 0) -!199 = !DISubroutineType(types: !200) -!200 = !{!201, !119, !147, !6} -!201 = !DIBasicType(name: "long long unsigned int", size: 64, encoding: DW_ATE_unsigned) -!202 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !172, entity: !203, file: !30, line: 231) -!203 = !DISubprogram(name: "strtof", scope: !23, file: !23, line: 124, type: !204, flags: DIFlagPrototyped, spFlags: 0) -!204 = !DISubroutineType(types: !205) -!205 = !{!206, !119, !147} -!206 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) -!207 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !172, entity: !208, file: !30, line: 232) -!208 = !DISubprogram(name: "strtold", scope: !23, file: !23, line: 127, type: !209, flags: DIFlagPrototyped, spFlags: 0) -!209 = !DISubroutineType(types: !210) -!210 = !{!211, !119, !147} -!211 = !DIBasicType(name: "long double", size: 128, encoding: DW_ATE_float) -!212 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !173, file: !30, line: 240) -!213 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !180, file: !30, line: 242) -!214 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !182, file: !30, line: 244) -!215 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !216, file: !30, line: 245) -!216 = !DISubprogram(name: "div", linkageName: "_ZN9__gnu_cxx3divExx", scope: !172, file: !30, line: 213, type: !187, flags: DIFlagPrototyped, spFlags: 0) -!217 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !186, file: !30, line: 246) -!218 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !190, file: !30, line: 248) -!219 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !203, file: !30, line: 249) -!220 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !194, file: !30, line: 250) -!221 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !198, file: !30, line: 251) -!222 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !208, file: !30, line: 252) -!223 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !39, file: !224, line: 38) -!224 = !DIFile(filename: "/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/stdlib.h", directory: "") -!225 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !43, file: !224, line: 39) -!226 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !84, file: !224, line: 40) -!227 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !48, file: !224, line: 43) -!228 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !129, file: !224, line: 46) -!229 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !28, file: !224, line: 51) -!230 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !32, file: !224, line: 52) -!231 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !232, file: !224, line: 54) -!232 = !DISubprogram(name: "abs", linkageName: "_ZSt3absg", scope: !21, file: !26, line: 103, type: !233, flags: DIFlagPrototyped, spFlags: 0) -!233 = !DISubroutineType(types: !234) -!234 = !{!235, !235} -!235 = !DIBasicType(name: "__float128", size: 128, encoding: DW_ATE_float) -!236 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !50, file: !224, line: 55) -!237 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !54, file: !224, line: 56) -!238 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !58, file: !224, line: 57) -!239 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !62, file: !224, line: 58) -!240 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !76, file: !224, line: 59) -!241 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !216, file: !224, line: 60) -!242 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !88, file: !224, line: 61) -!243 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !92, file: !224, line: 62) -!244 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !97, file: !224, line: 63) -!245 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !101, file: !224, line: 64) -!246 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !105, file: !224, line: 65) -!247 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !109, file: !224, line: 67) -!248 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !113, file: !224, line: 68) -!249 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !121, file: !224, line: 69) -!250 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !125, file: !224, line: 71) -!251 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !131, file: !224, line: 72) -!252 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !135, file: !224, line: 73) -!253 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !139, file: !224, line: 74) -!254 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !144, file: !224, line: 75) -!255 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !150, file: !224, line: 76) -!256 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !154, file: !224, line: 77) -!257 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !158, file: !224, line: 78) -!258 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !160, file: !224, line: 80) -!259 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !168, file: !224, line: 81) -!260 = !{i32 7, !"Dwarf Version", i32 4} -!261 = !{i32 2, !"Debug Info Version", i32 3} -!262 = !{i32 1, !"wchar_size", i32 4} -!263 = !{i32 7, !"PIC Level", i32 2} -!264 = !{!"clang version 11.1.0 (https://github.com/llvm/llvm-project.git 7e99bddfeaab2713a8bb6ca538da25b66e6efc59)"} -!265 = distinct !DISubprogram(name: "perform_calculation", linkageName: "_Z19perform_calculationPdii", scope: !3, file: !3, line: 4, type: !266, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !11, retainedNodes: !12) -!266 = !DISubroutineType(types: !267) -!267 = !{null, !14, !6, !6} -!268 = !DILocalVariable(name: "base", arg: 1, scope: !265, file: !3, line: 4, type: !14) -!269 = !DILocation(line: 4, column: 34, scope: !265) -!270 = !DILocalVariable(name: "offset_1", arg: 2, scope: !265, file: !3, line: 4, type: !6) -!271 = !DILocation(line: 4, column: 44, scope: !265) -!272 = !DILocalVariable(name: "offset_2", arg: 3, scope: !265, file: !3, line: 4, type: !6) -!273 = !DILocation(line: 4, column: 58, scope: !265) -!274 = !DILocation(line: 4, column: 92, scope: !265) -!275 = !DILocation(line: 4, column: 97, scope: !265) -!276 = !DILocation(line: 4, column: 90, scope: !265) -!277 = !DILocation(line: 4, column: 70, scope: !265) -!278 = !DILocation(line: 4, column: 75, scope: !265) -!279 = !DILocation(line: 4, column: 85, scope: !265) -!280 = !DILocation(line: 4, column: 108, scope: !265) -!281 = distinct !DISubprogram(name: "doall_possible", linkageName: "_Z14doall_possiblePdi", scope: !3, file: !3, line: 6, type: !282, scopeLine: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !11, retainedNodes: !12) -!282 = !DISubroutineType(types: !283) -!283 = !{null, !14, !6} -!284 = !DILocalVariable(name: "base", arg: 1, scope: !281, file: !3, line: 6, type: !14) -!285 = !DILocation(line: 6, column: 29, scope: !281) -!286 = !DILocalVariable(name: "index", arg: 2, scope: !281, file: !3, line: 6, type: !6) -!287 = !DILocation(line: 6, column: 39, scope: !281) -!288 = !DILocation(line: 6, column: 68, scope: !281) -!289 = !DILocation(line: 6, column: 74, scope: !281) -!290 = !DILocation(line: 6, column: 81, scope: !281) -!291 = !DILocation(line: 6, column: 48, scope: !281) -!292 = !DILocation(line: 6, column: 89, scope: !281) -!293 = distinct !DISubprogram(name: "doall_not_possible", linkageName: "_Z18doall_not_possiblePdii", scope: !3, file: !3, line: 8, type: !266, scopeLine: 8, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !11, retainedNodes: !12) -!294 = !DILocalVariable(name: "base", arg: 1, scope: !293, file: !3, line: 8, type: !14) -!295 = !DILocation(line: 8, column: 33, scope: !293) -!296 = !DILocalVariable(name: "index", arg: 2, scope: !293, file: !3, line: 8, type: !6) -!297 = !DILocation(line: 8, column: 43, scope: !293) -!298 = !DILocalVariable(name: "n", arg: 3, scope: !293, file: !3, line: 8, type: !6) -!299 = !DILocation(line: 8, column: 54, scope: !293) -!300 = !DILocation(line: 8, column: 79, scope: !293) -!301 = !DILocation(line: 8, column: 85, scope: !293) -!302 = !DILocation(line: 8, column: 93, scope: !293) -!303 = !DILocation(line: 8, column: 107, scope: !293) -!304 = !DILocation(line: 8, column: 105, scope: !293) -!305 = !DILocation(line: 8, column: 99, scope: !293) -!306 = !DILocation(line: 8, column: 59, scope: !293) -!307 = !DILocation(line: 8, column: 112, scope: !293) -!308 = !DILocalVariable(name: "argc", arg: 1, scope: !2, file: !3, line: 10, type: !6) -!309 = !DILocation(line: 10, column: 14, scope: !2) -!310 = !DILocalVariable(name: "argv", arg: 2, scope: !2, file: !3, line: 10, type: !7) -!311 = !DILocation(line: 10, column: 32, scope: !2) -!312 = !DILocalVariable(name: "x", scope: !2, file: !3, line: 13, type: !14) -!313 = !DILocation(line: 13, column: 11, scope: !2) -!314 = !DILocation(line: 13, column: 32, scope: !2) -!315 = !DILocation(line: 13, column: 34, scope: !2) -!316 = !DILocation(line: 13, column: 25, scope: !2) -!317 = !DILocation(line: 13, column: 15, scope: !2) -!318 = !DILocalVariable(name: "i", scope: !319, file: !3, line: 17, type: !6) -!319 = distinct !DILexicalBlock(scope: !2, file: !3, line: 17, column: 3) -!320 = !DILocation(line: 17, column: 12, scope: !319) -!321 = !DILocation(line: 17, column: 8, scope: !319) -!322 = !DILocation(line: 17, column: 19, scope: !323) -!323 = distinct !DILexicalBlock(scope: !319, file: !3, line: 17, column: 3) -!324 = !DILocation(line: 17, column: 23, scope: !323) -!325 = !DILocation(line: 17, column: 21, scope: !323) -!326 = !DILocation(line: 17, column: 3, scope: !319) -!327 = !DILocation(line: 18, column: 5, scope: !328) -!328 = distinct !DILexicalBlock(scope: !323, file: !3, line: 17, column: 31) -!329 = !DILocation(line: 18, column: 7, scope: !328) -!330 = !DILocation(line: 18, column: 10, scope: !328) -!331 = !DILocation(line: 19, column: 3, scope: !328) -!332 = !DILocation(line: 17, column: 26, scope: !323) -!333 = !DILocation(line: 17, column: 3, scope: !323) -!334 = distinct !{!334, !326, !335} -!335 = !DILocation(line: 19, column: 3, scope: !319) -!336 = !DILocalVariable(name: "i", scope: !337, file: !3, line: 22, type: !6) -!337 = distinct !DILexicalBlock(scope: !2, file: !3, line: 22, column: 3) -!338 = !DILocation(line: 22, column: 12, scope: !337) -!339 = !DILocation(line: 22, column: 8, scope: !337) -!340 = !DILocation(line: 22, column: 19, scope: !341) -!341 = distinct !DILexicalBlock(scope: !337, file: !3, line: 22, column: 3) -!342 = !DILocation(line: 22, column: 23, scope: !341) -!343 = !DILocation(line: 22, column: 21, scope: !341) -!344 = !DILocation(line: 22, column: 3, scope: !337) -!345 = !DILocation(line: 23, column: 20, scope: !346) -!346 = distinct !DILexicalBlock(scope: !341, file: !3, line: 22, column: 31) -!347 = !DILocation(line: 23, column: 23, scope: !346) -!348 = !DILocation(line: 23, column: 5, scope: !346) -!349 = !DILocation(line: 24, column: 3, scope: !346) -!350 = !DILocation(line: 22, column: 27, scope: !341) -!351 = !DILocation(line: 22, column: 3, scope: !341) -!352 = distinct !{!352, !344, !353} -!353 = !DILocation(line: 24, column: 3, scope: !337) -!354 = !DILocalVariable(name: "i", scope: !355, file: !3, line: 27, type: !6) -!355 = distinct !DILexicalBlock(scope: !2, file: !3, line: 27, column: 3) -!356 = !DILocation(line: 27, column: 12, scope: !355) -!357 = !DILocation(line: 27, column: 8, scope: !355) -!358 = !DILocation(line: 27, column: 19, scope: !359) -!359 = distinct !DILexicalBlock(scope: !355, file: !3, line: 27, column: 3) -!360 = !DILocation(line: 27, column: 23, scope: !359) -!361 = !DILocation(line: 27, column: 21, scope: !359) -!362 = !DILocation(line: 27, column: 3, scope: !355) -!363 = !DILocation(line: 28, column: 24, scope: !364) -!364 = distinct !DILexicalBlock(scope: !359, file: !3, line: 27, column: 31) -!365 = !DILocation(line: 28, column: 27, scope: !364) -!366 = !DILocation(line: 28, column: 30, scope: !364) -!367 = !DILocation(line: 28, column: 5, scope: !364) -!368 = !DILocation(line: 29, column: 3, scope: !364) -!369 = !DILocation(line: 27, column: 27, scope: !359) -!370 = !DILocation(line: 27, column: 3, scope: !359) -!371 = distinct !{!371, !362, !372} -!372 = !DILocation(line: 29, column: 3, scope: !355) -!373 = !DILocation(line: 31, column: 8, scope: !2) -!374 = !DILocation(line: 31, column: 3, scope: !2) -!375 = !DILocation(line: 33, column: 3, scope: !2) diff --git a/test/end_to_end/optimizer/loop_collapse/positive/simple_1/src/FileMapping.txt b/test/end_to_end/optimizer/loop_collapse/positive/simple_1/src/FileMapping.txt new file mode 100644 index 000000000..982301711 --- /dev/null +++ b/test/end_to_end/optimizer/loop_collapse/positive/simple_1/src/FileMapping.txt @@ -0,0 +1 @@ +1 /home/lukas/git/discopop/test/end_to_end/optimizer/loop_collapse/positive/simple_1/src/code.cpp diff --git a/test/end_to_end/reduction_pattern/negative/case_1/src/FileMapping.txt b/test/end_to_end/reduction_pattern/negative/case_1/src/FileMapping.txt new file mode 100644 index 000000000..8b05d2182 --- /dev/null +++ b/test/end_to_end/reduction_pattern/negative/case_1/src/FileMapping.txt @@ -0,0 +1 @@ +1 /home/lukas/git/discopop/test/end_to_end/reduction_pattern/negative/case_1/src/code.cpp diff --git a/test/end_to_end/reduction_pattern/negative/case_1/src/code.ll b/test/end_to_end/reduction_pattern/negative/case_1/src/code.ll new file mode 100644 index 000000000..8a5836cf6 --- /dev/null +++ b/test/end_to_end/reduction_pattern/negative/case_1/src/code.ll @@ -0,0 +1,427 @@ +; ModuleID = 'code.cpp' +source_filename = "code.cpp" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@.str = private unnamed_addr constant [8 x i8] c"1:1;1:3\00", align 1 +@.str.1 = private unnamed_addr constant [8 x i8] c"1:1;1:5\00", align 1 +@.str.2 = private unnamed_addr constant [8 x i8] c"1:2;1:3\00", align 1 +@.str.3 = private unnamed_addr constant [8 x i8] c"1:2;1:5\00", align 1 +@.str.4 = private unnamed_addr constant [7 x i8] c"retval\00", align 1 +@.str.5 = private unnamed_addr constant [2 x i8] c"i\00", align 1 +@.str.6 = private unnamed_addr constant [10 x i8] c"1:15;1:16\00", align 1 +@.str.7 = private unnamed_addr constant [10 x i8] c"1:15;1:18\00", align 1 +@.str.8 = private unnamed_addr constant [10 x i8] c"1:15;1:19\00", align 1 +@.str.9 = private unnamed_addr constant [10 x i8] c"1:21;1:22\00", align 1 +@.str.10 = private unnamed_addr constant [10 x i8] c"1:21;1:26\00", align 1 +@.str.11 = private unnamed_addr constant [5 x i8] c".str\00", align 1 +@.str.12 = private unnamed_addr constant [7 x i8] c".str.1\00", align 1 +@.str.13 = private unnamed_addr constant [7 x i8] c".str.2\00", align 1 +@.str.14 = private unnamed_addr constant [7 x i8] c".str.3\00", align 1 +@.str.15 = private unnamed_addr constant [7 x i8] c".str.4\00", align 1 +@.str.16 = private unnamed_addr constant [7 x i8] c".str.5\00", align 1 +@.str.17 = private unnamed_addr constant [7 x i8] c".str.6\00", align 1 +@.str.18 = private unnamed_addr constant [7 x i8] c".str.7\00", align 1 +@.str.19 = private unnamed_addr constant [7 x i8] c".str.8\00", align 1 +@.str.20 = private unnamed_addr constant [7 x i8] c".str.9\00", align 1 +@.str.21 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1 +@.str.22 = private unnamed_addr constant [2 x i8] c"N\00", align 1 +@.str.23 = private unnamed_addr constant [12 x i8] c"saved_stack\00", align 1 +@.str.24 = private unnamed_addr constant [12 x i8] c"__vla_expr0\00", align 1 +@.str.25 = private unnamed_addr constant [2 x i8] c"w\00", align 1 +@.str.26 = private unnamed_addr constant [4 x i8] c"Arr\00", align 1 + +; Function Attrs: noinline nounwind optnone uwtable +define i32 @_Z1fi(i32 %i) #0 !dbg !8 { +entry: + call void @__dp_func_entry(i32 16387, i32 0) + %__dp_bb1 = alloca i32, align 4 + store i32 0, i32* %__dp_bb1, align 4 + %__dp_bb = alloca i32, align 4 + store i32 0, i32* %__dp_bb, align 4 + %retval = alloca i32, align 4 + %0 = ptrtoint i32* %retval to i64 + %i.addr = alloca i32, align 4 + %1 = ptrtoint i32* %i.addr to i64 + %2 = ptrtoint i32* %i.addr to i64 + store i32 %i, i32* %i.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %i.addr, metadata !12, metadata !DIExpression()), !dbg !13 + %3 = ptrtoint i32* %i.addr to i64 + %4 = load i32, i32* %i.addr, align 4, !dbg !14 + %cmp = icmp slt i32 %4, 50000, !dbg !16 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0), i1 %cmp, i32 1), !dbg !17 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.1, i32 0, i32 0), i1 %cmp, i32 0), !dbg !17 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.2, i32 0, i32 0), i1 %cmp, i32 1), !dbg !17 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.3, i32 0, i32 0), i1 %cmp, i32 0), !dbg !17 + call void @__dp_report_bb(i32 0) + br i1 %cmp, label %if.then, label %if.else, !dbg !17 + +if.then: ; preds = %entry + %5 = ptrtoint i32* %i.addr to i64 + %6 = load i32, i32* %i.addr, align 4, !dbg !18 + %add = add nsw i32 %6, 50000, !dbg !20 + %7 = ptrtoint i32* %retval to i64 + store i32 %add, i32* %retval, align 4, !dbg !21 + call void @__dp_report_bb(i32 1) + store i32 1, i32* %__dp_bb, align 4 + br label %return, !dbg !21 + +if.else: ; preds = %entry + %8 = ptrtoint i32* %i.addr to i64 + %9 = load i32, i32* %i.addr, align 4, !dbg !22 + %10 = ptrtoint i32* %retval to i64 + store i32 %9, i32* %retval, align 4, !dbg !24 + call void @__dp_report_bb(i32 2) + store i32 1, i32* %__dp_bb1, align 4 + br label %return, !dbg !24 + +return: ; preds = %if.else, %if.then + %11 = ptrtoint i32* %retval to i64 + %12 = load i32, i32* %retval, align 4, !dbg !25 + %13 = load i32, i32* %__dp_bb, align 4 + call void @__dp_report_bb_pair(i32 %13, i32 3) + %14 = load i32, i32* %__dp_bb1, align 4 + call void @__dp_report_bb_pair(i32 %14, i32 4) + call void @__dp_func_exit(i32 16393, i32 0), !dbg !25 + ret i32 %12, !dbg !25 +} + +; Function Attrs: nounwind readnone speculatable willreturn +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +; Function Attrs: noinline nounwind optnone uwtable +define i32 @_Z1gi(i32 %i) #0 !dbg !26 { +entry: + call void @__dp_func_entry(i32 16395, i32 0) + %i.addr = alloca i32, align 4 + %0 = ptrtoint i32* %i.addr to i64 + %1 = ptrtoint i32* %i.addr to i64 + store i32 %i, i32* %i.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %i.addr, metadata !27, metadata !DIExpression()), !dbg !28 + %2 = ptrtoint i32* %i.addr to i64 + %3 = load i32, i32* %i.addr, align 4, !dbg !29 + call void @__dp_report_bb(i32 5) + call void @__dp_func_exit(i32 16395, i32 0), !dbg !30 + ret i32 %3, !dbg !30 +} + +; Function Attrs: noinline norecurse nounwind optnone uwtable +define i32 @main() #2 !dbg !31 { +entry: + call void @__dp_func_entry(i32 16397, i32 1) + %__dp_bb14 = alloca i32, align 4 + store i32 0, i32* %__dp_bb14, align 4 + %__dp_bb13 = alloca i32, align 4 + store i32 0, i32* %__dp_bb13, align 4 + %__dp_bb = alloca i32, align 4 + store i32 0, i32* %__dp_bb, align 4 + %retval = alloca i32, align 4 + %0 = ptrtoint i32* %retval to i64 + %N = alloca i32, align 4 + %1 = ptrtoint i32* %N to i64 + %saved_stack = alloca i8*, align 8 + %2 = ptrtoint i8** %saved_stack to i64 + %__vla_expr0 = alloca i64, align 8 + %3 = ptrtoint i64* %__vla_expr0 to i64 + %i = alloca i32, align 4 + %4 = ptrtoint i32* %i to i64 + %w = alloca i64, align 8 + %5 = ptrtoint i64* %w to i64 + %i1 = alloca i32, align 4 + %6 = ptrtoint i32* %i1 to i64 + %7 = ptrtoint i32* %retval to i64 + store i32 0, i32* %retval, align 4 + call void @llvm.dbg.declare(metadata i32* %N, metadata !34, metadata !DIExpression()), !dbg !35 + %8 = ptrtoint i32* %N to i64 + store i32 100000, i32* %N, align 4, !dbg !35 + %9 = ptrtoint i32* %N to i64 + %10 = load i32, i32* %N, align 4, !dbg !36 + %11 = zext i32 %10 to i64, !dbg !37 + call void @__dp_call(i32 16399), !dbg !37 + %12 = call i8* @llvm.stacksave(), !dbg !37 + %13 = ptrtoint i8** %saved_stack to i64 + store i8* %12, i8** %saved_stack, align 8, !dbg !37 + %vla = alloca i32, i64 %11, align 16, !dbg !37 + %14 = ptrtoint i32* %vla to i64, !dbg !37 + %15 = add i64 %14, %11, !dbg !37 + %16 = mul i64 %11, 4, !dbg !37 + call void @__dp_alloca(i32 16399, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.26, i32 0, i32 0), i64 %14, i64 %15, i64 %16, i64 %11), !dbg !37 + %17 = ptrtoint i64* %__vla_expr0 to i64 + store i64 %11, i64* %__vla_expr0, align 8, !dbg !37 + call void @llvm.dbg.declare(metadata i64* %__vla_expr0, metadata !38, metadata !DIExpression()), !dbg !40 + call void @llvm.dbg.declare(metadata i32* %vla, metadata !41, metadata !DIExpression()), !dbg !45 + call void @llvm.dbg.declare(metadata i32* %i, metadata !46, metadata !DIExpression()), !dbg !48 + %18 = ptrtoint i32* %i to i64 + store i32 0, i32* %i, align 4, !dbg !48 + call void @__dp_report_bb(i32 6) + br label %for.cond, !dbg !49 + +for.cond: ; preds = %for.inc, %entry + call void @__dp_loop_entry(i32 16402, i32 0) + %19 = ptrtoint i32* %i to i64 + %20 = load i32, i32* %i, align 4, !dbg !50 + %21 = ptrtoint i32* %N to i64 + %22 = load i32, i32* %N, align 4, !dbg !52 + %cmp = icmp slt i32 %20, %22, !dbg !53 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.6, i32 0, i32 0), i1 %cmp, i32 1), !dbg !54 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.7, i32 0, i32 0), i1 %cmp, i32 0), !dbg !54 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.8, i32 0, i32 0), i1 %cmp, i32 0), !dbg !54 + call void @__dp_report_bb(i32 9) + %23 = load i32, i32* %__dp_bb, align 4 + call void @__dp_report_bb_pair(i32 %23, i32 16) + br i1 %cmp, label %for.body, label %for.end, !dbg !54 + +for.body: ; preds = %for.cond + call void @__dp_loop_incr(i32 2) + %24 = ptrtoint i32* %i to i64 + %25 = load i32, i32* %i, align 4, !dbg !55 + %idxprom = sext i32 %25 to i64, !dbg !57 + %arrayidx = getelementptr inbounds i32, i32* %vla, i64 %idxprom, !dbg !57 + %26 = ptrtoint i32* %arrayidx to i64 + call void @__dp_write(i32 16403, i64 %26, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.26, i32 0, i32 0)) + store i32 0, i32* %arrayidx, align 4, !dbg !58 + call void @__dp_report_bb(i32 7) + %27 = load i32, i32* %__dp_bb, align 4 + call void @__dp_report_bb_pair(i32 %27, i32 15) + br label %for.inc, !dbg !59 + +for.inc: ; preds = %for.body + %28 = ptrtoint i32* %i to i64 + %29 = load i32, i32* %i, align 4, !dbg !60 + %inc = add nsw i32 %29, 1, !dbg !60 + %30 = ptrtoint i32* %i to i64 + store i32 %inc, i32* %i, align 4, !dbg !60 + call void @__dp_report_bb(i32 10) + %31 = load i32, i32* %__dp_bb, align 4 + call void @__dp_report_bb_pair(i32 %31, i32 17) + store i32 1, i32* %__dp_bb, align 4 + br label %for.cond, !dbg !61, !llvm.loop !62 + +for.end: ; preds = %for.cond + call void @__dp_loop_exit(i32 16406, i32 0) + call void @llvm.dbg.declare(metadata i64* %w, metadata !64, metadata !DIExpression()), !dbg !66 + %32 = ptrtoint i64* %w to i64 + store i64 0, i64* %w, align 8, !dbg !66 + call void @llvm.dbg.declare(metadata i32* %i1, metadata !67, metadata !DIExpression()), !dbg !69 + %33 = ptrtoint i32* %i1 to i64 + store i32 0, i32* %i1, align 4, !dbg !69 + call void @__dp_report_bb(i32 8) + br label %for.cond2, !dbg !70 + +for.cond2: ; preds = %for.inc10, %for.end + call void @__dp_loop_entry(i32 16409, i32 1) + %34 = ptrtoint i32* %i1 to i64 + %35 = load i32, i32* %i1, align 4, !dbg !71 + %36 = ptrtoint i32* %N to i64 + %37 = load i32, i32* %N, align 4, !dbg !73 + %cmp3 = icmp slt i32 %35, %37, !dbg !74 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.9, i32 0, i32 0), i1 %cmp3, i32 1), !dbg !75 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.10, i32 0, i32 0), i1 %cmp3, i32 0), !dbg !75 + call void @__dp_report_bb(i32 12) + %38 = load i32, i32* %__dp_bb13, align 4 + call void @__dp_report_bb_pair(i32 %38, i32 18) + br i1 %cmp3, label %for.body4, label %for.end12, !dbg !75 + +for.body4: ; preds = %for.cond2 + call void @__dp_loop_incr(i32 1) + %39 = ptrtoint i32* %i1 to i64 + %40 = load i32, i32* %i1, align 4, !dbg !76 + call void @__dp_call(i32 16410), !dbg !78 + %call = call i32 @_Z1gi(i32 %40), !dbg !78 + %idxprom5 = sext i32 %call to i64, !dbg !79 + %arrayidx6 = getelementptr inbounds i32, i32* %vla, i64 %idxprom5, !dbg !79 + %41 = ptrtoint i32* %arrayidx6 to i64 + call void @__dp_read(i32 16410, i64 %41, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.26, i32 0, i32 0)) + %42 = load i32, i32* %arrayidx6, align 4, !dbg !79 + %conv = sext i32 %42 to i64, !dbg !79 + %43 = ptrtoint i64* %w to i64 + %44 = load i64, i64* %w, align 8, !dbg !80 + %add = add nsw i64 %44, %conv, !dbg !80 + %45 = ptrtoint i64* %w to i64 + store i64 %add, i64* %w, align 8, !dbg !80 + %46 = ptrtoint i32* %i1 to i64 + %47 = load i32, i32* %i1, align 4, !dbg !81 + call void @__dp_call(i32 16411), !dbg !82 + %call7 = call i32 @_Z1fi(i32 %47), !dbg !82 + %idxprom8 = sext i32 %call7 to i64, !dbg !83 + %arrayidx9 = getelementptr inbounds i32, i32* %vla, i64 %idxprom8, !dbg !83 + %48 = ptrtoint i32* %arrayidx9 to i64 + call void @__dp_write(i32 16411, i64 %48, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.26, i32 0, i32 0)) + store i32 1, i32* %arrayidx9, align 4, !dbg !84 + call void @__dp_report_bb(i32 14) + %49 = load i32, i32* %__dp_bb13, align 4 + call void @__dp_report_bb_pair(i32 %49, i32 20) + %50 = load i32, i32* %__dp_bb14, align 4 + call void @__dp_report_bb_pair(i32 %50, i32 21) + store i32 1, i32* %__dp_bb14, align 4 + br label %for.inc10, !dbg !85 + +for.inc10: ; preds = %for.body4 + %51 = ptrtoint i32* %i1 to i64 + %52 = load i32, i32* %i1, align 4, !dbg !86 + %inc11 = add nsw i32 %52, 1, !dbg !86 + %53 = ptrtoint i32* %i1 to i64 + store i32 %inc11, i32* %i1, align 4, !dbg !86 + call void @__dp_report_bb(i32 13) + %54 = load i32, i32* %__dp_bb13, align 4 + call void @__dp_report_bb_pair(i32 %54, i32 19) + store i32 1, i32* %__dp_bb13, align 4 + br label %for.cond2, !dbg !87, !llvm.loop !88 + +for.end12: ; preds = %for.cond2 + call void @__dp_loop_exit(i32 16413, i32 1) + %55 = ptrtoint i8** %saved_stack to i64 + %56 = load i8*, i8** %saved_stack, align 8, !dbg !90 + call void @__dp_call(i32 16413), !dbg !90 + call void @llvm.stackrestore(i8* %56), !dbg !90 + %57 = ptrtoint i32* %retval to i64 + %58 = load i32, i32* %retval, align 4, !dbg !90 + call void @__dp_report_bb(i32 11) + call void @__dp_finalize(i32 16413), !dbg !90 + call void @__dp_loop_output(), !dbg !90 + call void @__dp_taken_branch_counter_output(), !dbg !90 + ret i32 %58, !dbg !90 +} + +; Function Attrs: nounwind +declare i8* @llvm.stacksave() #3 + +; Function Attrs: nounwind +declare void @llvm.stackrestore(i8*) #3 + +declare void @__dp_init(i32, i32, i32) + +declare void @__dp_finalize(i32) + +declare void @__dp_read(i32, i64, i8*) + +declare void @__dp_write(i32, i64, i8*) + +declare void @__dp_alloca(i32, i8*, i64, i64, i64, i64) + +declare void @__dp_new(i32, i64, i64, i64) + +declare void @__dp_delete(i32, i64) + +declare void @__dp_call(i32) + +declare void @__dp_func_entry(i32, i32) + +declare void @__dp_func_exit(i32, i32) + +declare void @__dp_loop_entry(i32, i32) + +declare void @__dp_loop_exit(i32, i32) + +declare void @__dp_incr_taken_branch_counter(i8*, i32, i32) + +declare void @__dp_report_bb(i32) + +declare void @__dp_report_bb_pair(i32, i32) + +declare void @__dp_loop_incr(i32) + +declare void @__dp_loop_output() + +declare void @__dp_taken_branch_counter_output() + +attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind readnone speculatable willreturn } +attributes #2 = { noinline norecurse nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #3 = { nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5, !6} +!llvm.ident = !{!7} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 11.1.0 (https://github.com/llvm/llvm-project.git 7e99bddfeaab2713a8bb6ca538da25b66e6efc59)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "code.cpp", directory: "/home/lukas/git/discopop/test/end_to_end/reduction_pattern/negative/case_1/src") +!2 = !{} +!3 = !{i32 7, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{i32 7, !"PIC Level", i32 2} +!7 = !{!"clang version 11.1.0 (https://github.com/llvm/llvm-project.git 7e99bddfeaab2713a8bb6ca538da25b66e6efc59)"} +!8 = distinct !DISubprogram(name: "f", linkageName: "_Z1fi", scope: !1, file: !1, line: 3, type: !9, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) +!9 = !DISubroutineType(types: !10) +!10 = !{!11, !11} +!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!12 = !DILocalVariable(name: "i", arg: 1, scope: !8, file: !1, line: 3, type: !11) +!13 = !DILocation(line: 3, column: 11, scope: !8) +!14 = !DILocation(line: 4, column: 7, scope: !15) +!15 = distinct !DILexicalBlock(scope: !8, file: !1, line: 4, column: 7) +!16 = !DILocation(line: 4, column: 9, scope: !15) +!17 = !DILocation(line: 4, column: 7, scope: !8) +!18 = !DILocation(line: 5, column: 12, scope: !19) +!19 = distinct !DILexicalBlock(scope: !15, file: !1, line: 4, column: 23) +!20 = !DILocation(line: 5, column: 14, scope: !19) +!21 = !DILocation(line: 5, column: 5, scope: !19) +!22 = !DILocation(line: 7, column: 12, scope: !23) +!23 = distinct !DILexicalBlock(scope: !15, file: !1, line: 6, column: 10) +!24 = !DILocation(line: 7, column: 5, scope: !23) +!25 = !DILocation(line: 9, column: 1, scope: !8) +!26 = distinct !DISubprogram(name: "g", linkageName: "_Z1gi", scope: !1, file: !1, line: 11, type: !9, scopeLine: 11, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) +!27 = !DILocalVariable(name: "i", arg: 1, scope: !26, file: !1, line: 11, type: !11) +!28 = !DILocation(line: 11, column: 11, scope: !26) +!29 = !DILocation(line: 11, column: 23, scope: !26) +!30 = !DILocation(line: 11, column: 16, scope: !26) +!31 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 13, type: !32, scopeLine: 13, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) +!32 = !DISubroutineType(types: !33) +!33 = !{!11} +!34 = !DILocalVariable(name: "N", scope: !31, file: !1, line: 14, type: !11) +!35 = !DILocation(line: 14, column: 7, scope: !31) +!36 = !DILocation(line: 15, column: 11, scope: !31) +!37 = !DILocation(line: 15, column: 3, scope: !31) +!38 = !DILocalVariable(name: "__vla_expr0", scope: !31, type: !39, flags: DIFlagArtificial) +!39 = !DIBasicType(name: "long unsigned int", size: 64, encoding: DW_ATE_unsigned) +!40 = !DILocation(line: 0, scope: !31) +!41 = !DILocalVariable(name: "Arr", scope: !31, file: !1, line: 15, type: !42) +!42 = !DICompositeType(tag: DW_TAG_array_type, baseType: !11, elements: !43) +!43 = !{!44} +!44 = !DISubrange(count: !38) +!45 = !DILocation(line: 15, column: 7, scope: !31) +!46 = !DILocalVariable(name: "i", scope: !47, file: !1, line: 18, type: !11) +!47 = distinct !DILexicalBlock(scope: !31, file: !1, line: 18, column: 3) +!48 = !DILocation(line: 18, column: 12, scope: !47) +!49 = !DILocation(line: 18, column: 8, scope: !47) +!50 = !DILocation(line: 18, column: 19, scope: !51) +!51 = distinct !DILexicalBlock(scope: !47, file: !1, line: 18, column: 3) +!52 = !DILocation(line: 18, column: 23, scope: !51) +!53 = !DILocation(line: 18, column: 21, scope: !51) +!54 = !DILocation(line: 18, column: 3, scope: !47) +!55 = !DILocation(line: 19, column: 9, scope: !56) +!56 = distinct !DILexicalBlock(scope: !51, file: !1, line: 18, column: 31) +!57 = !DILocation(line: 19, column: 5, scope: !56) +!58 = !DILocation(line: 19, column: 12, scope: !56) +!59 = !DILocation(line: 20, column: 3, scope: !56) +!60 = !DILocation(line: 18, column: 27, scope: !51) +!61 = !DILocation(line: 18, column: 3, scope: !51) +!62 = distinct !{!62, !54, !63} +!63 = !DILocation(line: 20, column: 3, scope: !47) +!64 = !DILocalVariable(name: "w", scope: !31, file: !1, line: 22, type: !65) +!65 = !DIBasicType(name: "long int", size: 64, encoding: DW_ATE_signed) +!66 = !DILocation(line: 22, column: 8, scope: !31) +!67 = !DILocalVariable(name: "i", scope: !68, file: !1, line: 25, type: !11) +!68 = distinct !DILexicalBlock(scope: !31, file: !1, line: 25, column: 3) +!69 = !DILocation(line: 25, column: 12, scope: !68) +!70 = !DILocation(line: 25, column: 8, scope: !68) +!71 = !DILocation(line: 25, column: 19, scope: !72) +!72 = distinct !DILexicalBlock(scope: !68, file: !1, line: 25, column: 3) +!73 = !DILocation(line: 25, column: 23, scope: !72) +!74 = !DILocation(line: 25, column: 21, scope: !72) +!75 = !DILocation(line: 25, column: 3, scope: !68) +!76 = !DILocation(line: 26, column: 16, scope: !77) +!77 = distinct !DILexicalBlock(scope: !72, file: !1, line: 25, column: 31) +!78 = !DILocation(line: 26, column: 14, scope: !77) +!79 = !DILocation(line: 26, column: 10, scope: !77) +!80 = !DILocation(line: 26, column: 7, scope: !77) +!81 = !DILocation(line: 27, column: 11, scope: !77) +!82 = !DILocation(line: 27, column: 9, scope: !77) +!83 = !DILocation(line: 27, column: 5, scope: !77) +!84 = !DILocation(line: 27, column: 15, scope: !77) +!85 = !DILocation(line: 28, column: 3, scope: !77) +!86 = !DILocation(line: 25, column: 27, scope: !72) +!87 = !DILocation(line: 25, column: 3, scope: !72) +!88 = distinct !{!88, !75, !89} +!89 = !DILocation(line: 28, column: 3, scope: !68) +!90 = !DILocation(line: 29, column: 1, scope: !31) diff --git a/test/end_to_end/reduction_pattern/positive/nested/OMPSCR/c_Mandelbrot/src/FileMapping.txt b/test/end_to_end/reduction_pattern/positive/nested/OMPSCR/c_Mandelbrot/src/FileMapping.txt new file mode 100644 index 000000000..46bd31fbb --- /dev/null +++ b/test/end_to_end/reduction_pattern/positive/nested/OMPSCR/c_Mandelbrot/src/FileMapping.txt @@ -0,0 +1 @@ +1 /home/lukas/git/discopop/test/end_to_end/reduction_pattern/positive/nested/OMPSCR/c_Mandelbrot/src/code.cpp diff --git a/test/utils/subprocess_wrapper/command_execution_wrapper.py b/test/utils/subprocess_wrapper/command_execution_wrapper.py index 93ca4e370..b7e61e505 100644 --- a/test/utils/subprocess_wrapper/command_execution_wrapper.py +++ b/test/utils/subprocess_wrapper/command_execution_wrapper.py @@ -9,6 +9,6 @@ def run_cmd(cmd: str, cwd: str, env): executable="/bin/bash", shell=True, env=env, - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL, +# stdout=subprocess.DEVNULL, +# stderr=subprocess.DEVNULL, ) From 179c8f81229038ce8c8524a7f0f3c149656f266d Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Fri, 12 Jul 2024 13:24:01 +0200 Subject: [PATCH 023/105] chore(CI): move to python 3.10 --- .github/workflows/ci.yml | 6 +++--- .../screens/widgets/ScrollableText.py | 5 +++-- test/utils/subprocess_wrapper/command_execution_wrapper.py | 4 ++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aca972912..bee5e9422 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,7 +35,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v4 with: - python-version: 3.8 + python-version: '3.10' cache: 'pip' # uses requirements.txt - name: Install Python dependencies @@ -76,7 +76,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v4 with: - python-version: 3.8 + python-version: '3.10' cache: 'pip' # uses requirements.txt - name: Install Python dependencies @@ -123,7 +123,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v4 with: - python-version: 3.8 + python-version: '3.10' cache: 'pip' # uses requirements.txt - name: Install Python dependencies diff --git a/DEPRECATED_discopop_wizard/screens/widgets/ScrollableText.py b/DEPRECATED_discopop_wizard/screens/widgets/ScrollableText.py index 775be77e3..51681dae7 100644 --- a/DEPRECATED_discopop_wizard/screens/widgets/ScrollableText.py +++ b/DEPRECATED_discopop_wizard/screens/widgets/ScrollableText.py @@ -7,14 +7,15 @@ # directory for details. import tkinter as tk -from tkinter import ttk +from tkinter import Tk, ttk +from typing import Union class ScrollableTextWidget(object): frame: tk.Frame text_container: tk.Text - def __init__(self, parent_frame): + def __init__(self, parent_frame: Union[tk.Frame, Tk]): self.frame = ttk.Frame(parent_frame) # type: ignore self.frame.pack(fill=tk.BOTH, expand=True) self.frame.rowconfigure(0, weight=1) diff --git a/test/utils/subprocess_wrapper/command_execution_wrapper.py b/test/utils/subprocess_wrapper/command_execution_wrapper.py index b7e61e505..93ca4e370 100644 --- a/test/utils/subprocess_wrapper/command_execution_wrapper.py +++ b/test/utils/subprocess_wrapper/command_execution_wrapper.py @@ -9,6 +9,6 @@ def run_cmd(cmd: str, cwd: str, env): executable="/bin/bash", shell=True, env=env, -# stdout=subprocess.DEVNULL, -# stderr=subprocess.DEVNULL, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, ) From 906c5e19be6e38176ac31904ca6df6f0a206fe20 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 9 Jul 2024 15:33:37 +0200 Subject: [PATCH 024/105] fix: potential false positive reduction --- .../pattern_detectors/do_all_detector.py | 3 +-- .../pattern_detectors/reduction_detector.py | 25 ++++++------------- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/discopop_explorer/pattern_detectors/do_all_detector.py b/discopop_explorer/pattern_detectors/do_all_detector.py index df6c7f387..af47fad6b 100644 --- a/discopop_explorer/pattern_detectors/do_all_detector.py +++ b/discopop_explorer/pattern_detectors/do_all_detector.py @@ -290,7 +290,7 @@ def __check_loop_dependencies( ) cond_2 = len([cf for cf in called_functions_lineids if cf in dep.metadata_inter_call_dep]) > 0 cond_3 = len([t for t in parent_loops if t in dep.metadata_inter_iteration_dep]) > 0 - if (cond_1) or ((cond_2) and (cond_3)): + if cond_1 or cond_2 or cond_3: return True # if it is an intra iteration dependency, it is problematic if it belongs to a parent loop else: @@ -416,7 +416,6 @@ def __get_parent_loops(pet: PEGraphX, root_loop: LoopNode) -> List[LineID]: if s not in visited and s not in queue: queue.append(s) - parents.remove(root_loop.id) return [pet.node_at(p).start_position() for p in parents] diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index 345fae5f8..1bb76fe30 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -261,24 +261,14 @@ def __check_loop_dependencies( else: # RAW does not target a reduction variable. # RAW problematic, if it is not an intra-iteration RAW. - if ( - not dep.intra_iteration - and (dep.metadata_intra_iteration_dep is None or len(dep.metadata_intra_iteration_dep) == 0) - and parent_function_lineid - in (dep.metadata_intra_call_dep if dep.metadata_intra_call_dep is not None else []) - ) or ( - ( - False - if dep.metadata_inter_call_dep is None - else (len([cf for cf in called_functions_lineids if cf in dep.metadata_inter_call_dep]) > 0) - ) - and ( - False - if dep.metadata_inter_iteration_dep is None - else (len([t for t in parent_loops if t in dep.metadata_inter_iteration_dep]) > 0) - ) - ): + cond_1 = (len(dep.metadata_intra_iteration_dep) == 0) and parent_function_lineid in ( + dep.metadata_intra_call_dep if dep.metadata_intra_call_dep is not None else [] + ) + cond_2 = len([cf for cf in called_functions_lineids if cf in dep.metadata_inter_call_dep]) > 0 + cond_3 = len([t for t in parent_loops if t in dep.metadata_inter_iteration_dep]) > 0 + if cond_1 or cond_2 or cond_3: return True + # check for elif dep.dtype == DepType.WAR: # check WAR dependencies # WAR problematic, if it is not an intra-iteration WAR and the variable is not private or firstprivate @@ -338,7 +328,6 @@ def __get_parent_loops(pet: PEGraphX, root_loop: LoopNode) -> List[LineID]: if s not in visited and s not in queue: queue.append(s) - parents.remove(root_loop.id) return [pet.node_at(p).start_position() for p in parents] From e5b41b791db09c29f4da2f0911d220eb3cd2b620 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Fri, 12 Jul 2024 16:50:54 +0200 Subject: [PATCH 025/105] fix(explorer): exception handling when profiling enabled --- discopop_explorer/discopop_explorer.py | 174 +++++++++++++------------ 1 file changed, 90 insertions(+), 84 deletions(-) diff --git a/discopop_explorer/discopop_explorer.py b/discopop_explorer/discopop_explorer.py index ee6cdf332..8c4c421ea 100644 --- a/discopop_explorer/discopop_explorer.py +++ b/discopop_explorer/discopop_explorer.py @@ -190,79 +190,102 @@ def run(arguments: ExplorerArguments) -> None: profile = cProfile.Profile() profile.enable() - if arguments.generate_data_cu_inst is not None: - # start generation of Data_CUInst and stop execution afterwards - from .generate_Data_CUInst import wrapper as generate_data_cuinst_wrapper + try: + if arguments.generate_data_cu_inst is not None: + # start generation of Data_CUInst and stop execution afterwards + from .generate_Data_CUInst import wrapper as generate_data_cuinst_wrapper + + generate_data_cuinst_wrapper( + arguments.cu_xml_file, + arguments.dep_file, + arguments.loop_counter_file, + arguments.reduction_file, + arguments.generate_data_cu_inst, + ) + sys.exit(0) + + print("Loading Hotspots...") + + hotspots = load_hotspots( + HotspotLoaderArguments( + verbose=True, + get_loops=True, + get_functions=True, + get_YES=True, + get_MAYBE=True, + get_NO=False, + log_level=arguments.log_level, + write_log=arguments.write_log, + ) + ) + + print("Done.") - generate_data_cuinst_wrapper( + start = time.time() + + res = __run( + arguments.project_path, arguments.cu_xml_file, arguments.dep_file, arguments.loop_counter_file, arguments.reduction_file, - arguments.generate_data_cu_inst, - ) - sys.exit(0) - - print("Loading Hotspots...") - - hotspots = load_hotspots( - HotspotLoaderArguments( - verbose=True, - get_loops=True, - get_functions=True, - get_YES=True, - get_MAYBE=True, - get_NO=False, - log_level=arguments.log_level, - write_log=arguments.write_log, + arguments.plugins, + file_mapping=arguments.file_mapping_file, + cu_inst_result_file=arguments.cu_inst_result_file, + llvm_cxxfilt_path=arguments.llvm_cxxfilt_path, + discopop_build_path=arguments.discopop_build_path, + enable_patterns=arguments.enable_patterns, + enable_task_pattern=arguments.enable_task_pattern, + enable_detection_of_scheduling_clauses=arguments.detect_scheduling_clauses, + hotspot_functions=hotspots, + load_existing_doall_and_reduction_patterns=arguments.load_existing_doall_and_reduction_patterns, ) - ) - - print("Done.") - - start = time.time() - - res = __run( - arguments.project_path, - arguments.cu_xml_file, - arguments.dep_file, - arguments.loop_counter_file, - arguments.reduction_file, - arguments.plugins, - file_mapping=arguments.file_mapping_file, - cu_inst_result_file=arguments.cu_inst_result_file, - llvm_cxxfilt_path=arguments.llvm_cxxfilt_path, - discopop_build_path=arguments.discopop_build_path, - enable_patterns=arguments.enable_patterns, - enable_task_pattern=arguments.enable_task_pattern, - enable_detection_of_scheduling_clauses=arguments.detect_scheduling_clauses, - hotspot_functions=hotspots, - load_existing_doall_and_reduction_patterns=arguments.load_existing_doall_and_reduction_patterns, - ) - - end = time.time() - - if arguments.enable_pet_dump_file is not None: - with open(arguments.enable_pet_dump_file, "w+") as f: - f.write(res.pet.dump_to_pickled_json()) - f.flush() - f.close() - - if arguments.enable_detection_result_dump_file is not None: - with open(arguments.enable_detection_result_dump_file, "w+") as f: - f.write(res.dump_to_pickled_json()) - f.flush() - f.close() - - if arguments.enable_json_file is None: - print(str(res)) - else: - # todo re-enable? - # print(str(res)) - # since PETGraphX is not JSON Serializable, delete the field prior to executing the serialization - del res.pet - with open(arguments.enable_json_file, "w+") as f: - json.dump(res, f, indent=2, cls=PatternBaseSerializer) + + end = time.time() + + if arguments.enable_pet_dump_file is not None: + with open(arguments.enable_pet_dump_file, "w+") as f: + f.write(res.pet.dump_to_pickled_json()) + f.flush() + f.close() + + if arguments.enable_detection_result_dump_file is not None: + with open(arguments.enable_detection_result_dump_file, "w+") as f: + f.write(res.dump_to_pickled_json()) + f.flush() + f.close() + + if arguments.enable_json_file is None: + print(str(res)) + else: + # todo re-enable? + # print(str(res)) + # since PETGraphX is not JSON Serializable, delete the field prior to executing the serialization + del res.pet + with open(arguments.enable_json_file, "w+") as f: + json.dump(res, f, indent=2, cls=PatternBaseSerializer) + + + + # initialize the line_mapping.json + initialize_line_mapping(load_file_mapping(arguments.file_mapping_file), arguments.project_path) + + print("Time taken for pattern detection: {0}".format(end - start)) + + # demonstration of Microbenchmark possibilities + if arguments.microbench_file is not None: + microbench_file = get_path( + arguments.project_path, arguments.microbench_file + ) # NOTE: the json file is not usually located in the project, this is just for demonstration purposes + if not os.path.isfile(microbench_file): + raise FileNotFoundError(f"Microbenchmark file not found: {microbench_file}") + extrapBench = ExtrapInterpolatedMicrobench(microbench_file) + sympyExpr = extrapBench.getFunctionSympy() + print(sympyExpr) + print(sympyExpr.free_symbols) + except BaseException: + # required to correctly write profiling data if the program terminates + pass if arguments.enable_profiling_dump_file is not None: profile.disable() @@ -271,20 +294,3 @@ def run(arguments: ExplorerArguments) -> None: with open(arguments.enable_profiling_dump_file, "w+") as f: stats = pstats2.Stats(profile, stream=f).sort_stats("time").reverse_order() stats.print_stats() - - # initialize the line_mapping.json - initialize_line_mapping(load_file_mapping(arguments.file_mapping_file), arguments.project_path) - - print("Time taken for pattern detection: {0}".format(end - start)) - - # demonstration of Microbenchmark possibilities - if arguments.microbench_file is not None: - microbench_file = get_path( - arguments.project_path, arguments.microbench_file - ) # NOTE: the json file is not usually located in the project, this is just for demonstration purposes - if not os.path.isfile(microbench_file): - raise FileNotFoundError(f"Microbenchmark file not found: {microbench_file}") - extrapBench = ExtrapInterpolatedMicrobench(microbench_file) - sympyExpr = extrapBench.getFunctionSympy() - print(sympyExpr) - print(sympyExpr.free_symbols) From 793e0a4020ec9e75f2053b1bc00eec6b79e180fa Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Mon, 15 Jul 2024 09:09:46 +0200 Subject: [PATCH 026/105] chore(build): cleanup warning messages --- rtlib/runtimeFunctionsGlobals.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/rtlib/runtimeFunctionsGlobals.cpp b/rtlib/runtimeFunctionsGlobals.cpp index 8b736ea43..a8a8f10d5 100644 --- a/rtlib/runtimeFunctionsGlobals.cpp +++ b/rtlib/runtimeFunctionsGlobals.cpp @@ -66,14 +66,12 @@ pthread_t *workers = nullptr; // worker threads #define XSTR(x) STR(x) #define STR(x) #x #ifdef DP_NUM_WORKERS -#pragma message "Profiler: set NUM_WORKERS to " XSTR(DP_NUM_WORKERS) int32_t NUM_WORKERS = DP_NUM_WORKERS; #else int32_t NUM_WORKERS = 3; // default number of worker threads (multiple workers // can potentially lead to non-deterministic results) #endif -#pragma message "Profiler: set NUM_WORKERS to " XSTR(NUM_WORKERS) AbstractShadow *singleThreadedExecutionSMem = nullptr; // used if NUM_WORKERS==0 int32_t CHUNK_SIZE = 500; // default number of addresses in each chunk From b72f848278c43b23fc6a1731c87e15959084c9fd Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Mon, 15 Jul 2024 15:18:57 +0200 Subject: [PATCH 027/105] fix(explorer): exception handling when profiling enabled --- discopop_explorer/discopop_explorer.py | 32 ++++++++++++++++++-------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/discopop_explorer/discopop_explorer.py b/discopop_explorer/discopop_explorer.py index 8c4c421ea..9d2280681 100644 --- a/discopop_explorer/discopop_explorer.py +++ b/discopop_explorer/discopop_explorer.py @@ -283,14 +283,26 @@ def run(arguments: ExplorerArguments) -> None: sympyExpr = extrapBench.getFunctionSympy() print(sympyExpr) print(sympyExpr.free_symbols) - except BaseException: - # required to correctly write profiling data if the program terminates - pass - if arguments.enable_profiling_dump_file is not None: - profile.disable() - if os.path.exists(arguments.enable_profiling_dump_file): - os.remove(arguments.enable_profiling_dump_file) - with open(arguments.enable_profiling_dump_file, "w+") as f: - stats = pstats2.Stats(profile, stream=f).sort_stats("time").reverse_order() - stats.print_stats() + # print profiling results + if arguments.enable_profiling_dump_file is not None: + profile.disable() + if os.path.exists(arguments.enable_profiling_dump_file): + os.remove(arguments.enable_profiling_dump_file) + with open(arguments.enable_profiling_dump_file, "w+") as f: + stats = pstats2.Stats(profile, stream=f).sort_stats("tottime").reverse_order() + stats.print_stats() + + except BaseException as be: + # required to correctly write profiling data if the program terminates + # print profiling results + if arguments.enable_profiling_dump_file is not None: + profile.disable() + if os.path.exists(arguments.enable_profiling_dump_file): + os.remove(arguments.enable_profiling_dump_file) + with open(arguments.enable_profiling_dump_file, "w+") as f: + stats = pstats2.Stats(profile, stream=f).sort_stats("tottime").reverse_order() + stats.print_stats() + raise be + + From fa8b969861bcb430683663922efa4067eb74bb64 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 16 Jul 2024 12:10:33 +0200 Subject: [PATCH 028/105] fix(explorer): default-enabled pattern types --- discopop_explorer/__main__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/discopop_explorer/__main__.py b/discopop_explorer/__main__.py index 7ae3388c9..e88fe6297 100644 --- a/discopop_explorer/__main__.py +++ b/discopop_explorer/__main__.py @@ -69,8 +69,8 @@ def parse_args() -> ExplorerArguments: help="Dump DetectionResult object to JSON file. If a path is given, the DetectionResult object is written to the given file, otherwise to detection_result_dump.json. Contents are equivalent to the json output. NOTE: This dump contains a dump of the PET Graph!", ) parser.add_argument( - "--enable-patterns", type=str, nargs="?", default="*", - help="Specify comma-separated list of pattern types to be identified. Options: reduction,doall,pipeline,geodec,simplegpu. Default: *", + "--enable-patterns", type=str, nargs="?", default="reduction,doall,pipeline,geodec", + help="Specify comma-separated list of pattern types to be identified. Options: reduction,doall,pipeline,geodec,simplegpu. Default: reduction,doall,pipeline,geodec", ) parser.add_argument("--load-existing-doall-and-reduction-patterns", action="store_true", help="Skip pattern detection and insert existing patterns.json contents into the created detection_result.json") parser.add_argument("--log", type=str, default="WARNING", help="Specify log level: DEBUG, INFO, WARNING, ERROR, CRITICAL") From f71dd3c9bba68e2af10b315710fe20bd3b3c3779 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 17 Jul 2024 14:47:46 +0200 Subject: [PATCH 029/105] Empirical autotuning of applicable suggestions (#640) * add autotuner module skeleton * setup logger * check folder structure * wip * wip (execute reference) * copy configurations * update FileMapping in copied folder * add notes * load hotspots and suggestions * identify applicable suggestions * apply suggestions * add reference for suggestion selection * greedy search * show speedup * cleanup output * fix: prevent unnecessary executions * formatting * mypy type fixes * cleanup folders * add timeout * updated organization chart * add documentation * add license tags * formatting --- discopop_explorer/PEGraphX.py | 2 +- discopop_explorer/discopop_explorer.py | 9 +- discopop_explorer/pattern_detection.py | 4 +- .../pattern_detectors/do_all_detector.py | 2 +- .../geometric_decomposition_detector.py | 2 +- .../pattern_detectors/pipeline_detector.py | 2 +- .../pattern_detectors/reduction_detector.py | 2 +- .../task_parallelism_detector.py | 2 +- discopop_explorer/utils.py | 4 +- .../EmpiricalAutotuning/ArgumentClasses.py | 50 ++++++ .../EmpiricalAutotuning/Autotuner.py | 142 ++++++++++++++++++ .../Classes/CodeConfiguration.py | 136 +++++++++++++++++ .../Classes/ExecutionResult.py | 23 +++ discopop_library/EmpiricalAutotuning/Types.py | 9 ++ .../EmpiricalAutotuning/__init__.py | 0 .../EmpiricalAutotuning/__main__.py | 50 ++++++ discopop_library/EmpiricalAutotuning/utils.py | 25 +++ .../HostpotLoader/HotspotLoaderArguments.py | 1 + .../HostpotLoader/hostpot_loader.py | 27 ++-- .../discopop_optimizer/PETParser/PETParser.py | 2 +- .../Variables/Experiment.py | 4 +- .../discopop_optimizer/optimizer.py | 1 + docs/tools/Autotuner.md | 41 +++++ docs/tools/Scripts_and_wrappers.md | 2 +- docs/tools/organization_chart.graphml | 59 +++++++- docs/tools/organization_chart.svg | 44 +++++- setup.py | 1 + 27 files changed, 603 insertions(+), 43 deletions(-) create mode 100644 discopop_library/EmpiricalAutotuning/ArgumentClasses.py create mode 100644 discopop_library/EmpiricalAutotuning/Autotuner.py create mode 100644 discopop_library/EmpiricalAutotuning/Classes/CodeConfiguration.py create mode 100644 discopop_library/EmpiricalAutotuning/Classes/ExecutionResult.py create mode 100644 discopop_library/EmpiricalAutotuning/Types.py create mode 100644 discopop_library/EmpiricalAutotuning/__init__.py create mode 100644 discopop_library/EmpiricalAutotuning/__main__.py create mode 100644 discopop_library/EmpiricalAutotuning/utils.py create mode 100644 docs/tools/Autotuner.md diff --git a/discopop_explorer/PEGraphX.py b/discopop_explorer/PEGraphX.py index 4129b03ee..2b0bcfec3 100644 --- a/discopop_explorer/PEGraphX.py +++ b/discopop_explorer/PEGraphX.py @@ -769,7 +769,7 @@ def map_static_and_dynamic_dependencies(self) -> None: def calculateFunctionMetadata( self, - hotspot_information: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]]] = None, + hotspot_information: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str, float]]]] = None, func_nodes: Optional[List[FunctionNode]] = None, ) -> None: # store id of parent function in each node diff --git a/discopop_explorer/discopop_explorer.py b/discopop_explorer/discopop_explorer.py index 9d2280681..27bbdc177 100644 --- a/discopop_explorer/discopop_explorer.py +++ b/discopop_explorer/discopop_explorer.py @@ -111,7 +111,7 @@ def __run( enable_patterns: str = "*", enable_task_pattern: bool = False, enable_detection_of_scheduling_clauses: bool = False, - hotspot_functions: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]]] = None, + hotspot_functions: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str, float]]]] = None, load_existing_doall_and_reduction_patterns: bool = False, ) -> DetectionResult: pet = PEGraphX.from_parsed_input(*parse_inputs(cu_xml, dep_file, reduction_file, file_mapping)) # type: ignore @@ -209,6 +209,7 @@ def run(arguments: ExplorerArguments) -> None: hotspots = load_hotspots( HotspotLoaderArguments( verbose=True, + dot_discopop_path=os.getcwd(), get_loops=True, get_functions=True, get_YES=True, @@ -265,8 +266,6 @@ def run(arguments: ExplorerArguments) -> None: with open(arguments.enable_json_file, "w+") as f: json.dump(res, f, indent=2, cls=PatternBaseSerializer) - - # initialize the line_mapping.json initialize_line_mapping(load_file_mapping(arguments.file_mapping_file), arguments.project_path) @@ -292,7 +291,7 @@ def run(arguments: ExplorerArguments) -> None: with open(arguments.enable_profiling_dump_file, "w+") as f: stats = pstats2.Stats(profile, stream=f).sort_stats("tottime").reverse_order() stats.print_stats() - + except BaseException as be: # required to correctly write profiling data if the program terminates # print profiling results @@ -304,5 +303,3 @@ def run(arguments: ExplorerArguments) -> None: stats = pstats2.Stats(profile, stream=f).sort_stats("tottime").reverse_order() stats.print_stats() raise be - - diff --git a/discopop_explorer/pattern_detection.py b/discopop_explorer/pattern_detection.py index cfb24a81f..e06fae48a 100644 --- a/discopop_explorer/pattern_detection.py +++ b/discopop_explorer/pattern_detection.py @@ -78,7 +78,7 @@ def detect_patterns( enable_patterns: str, enable_task_pattern: bool, enable_detection_of_scheduling_clauses: bool, - hotspots: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]]], + hotspots: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str, float]]]], ) -> DetectionResult: """Runs pattern discovery on the CU graph""" self.__merge(False, True) @@ -207,7 +207,7 @@ def load_existing_doall_and_reduction_patterns( enable_patterns: str, enable_task_pattern: bool, enable_detection_of_scheduling_clauses: bool, - hotspots: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]]], + hotspots: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str, float]]]], ) -> DetectionResult: """skips the pattern discovery on the CU graph and loads a pre-existing pattern file""" self.__merge(False, True) diff --git a/discopop_explorer/pattern_detectors/do_all_detector.py b/discopop_explorer/pattern_detectors/do_all_detector.py index af47fad6b..7d7de95ee 100644 --- a/discopop_explorer/pattern_detectors/do_all_detector.py +++ b/discopop_explorer/pattern_detectors/do_all_detector.py @@ -74,7 +74,7 @@ def __str__(self) -> str: def run_detection( pet: PEGraphX, - hotspots: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]]], + hotspots: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str, float]]]], reduction_info: List[ReductionInfo], ) -> List[DoAllInfo]: """Search for do-all loop pattern diff --git a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py index be004f323..d7e0a0988 100644 --- a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py +++ b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py @@ -81,7 +81,7 @@ def __str__(self) -> str: def run_detection( - pet: PEGraphX, hotspots: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]]] + pet: PEGraphX, hotspots: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str, float]]]] ) -> List[GDInfo]: """Detects geometric decomposition diff --git a/discopop_explorer/pattern_detectors/pipeline_detector.py b/discopop_explorer/pattern_detectors/pipeline_detector.py index 1646cd878..f3fc0c88d 100644 --- a/discopop_explorer/pattern_detectors/pipeline_detector.py +++ b/discopop_explorer/pattern_detectors/pipeline_detector.py @@ -156,7 +156,7 @@ def is_pipeline_subnode(root: Node, current: Node, children_start_lines: List[Li def run_detection( - pet: PEGraphX, hotspots: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]]] + pet: PEGraphX, hotspots: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str, float]]]] ) -> List[PipelineInfo]: """Search for pipeline pattern on all the loops in the graph except for doall loops diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index 1bb76fe30..3b4be08c9 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -68,7 +68,7 @@ def __str__(self) -> str: def run_detection( - pet: PEGraphX, hotspots: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]]] + pet: PEGraphX, hotspots: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str, float]]]] ) -> List[ReductionInfo]: """Search for reduction pattern diff --git a/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py b/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py index abfdf27e1..d14699ed4 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py @@ -77,7 +77,7 @@ def build_preprocessed_graph_and_run_detection( cu_inst_result_file: str, llvm_cxxfilt_path: Optional[str], discopop_build_path: Optional[str], - hotspots: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]]], + hotspots: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str, float]]]], reduction_info: List[ReductionInfo], ) -> List[PatternInfo]: """execute preprocessing of given cu xml file and construct a new cu graph. diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index b7c66de86..8f721d028 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -937,7 +937,7 @@ def __is_written_prior_to_task(pet: PEGraphX, var: Variable, task: Node) -> bool def filter_for_hotspots( pet: PEGraphX, nodes: List[Node], - hotspot_information: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]]], + hotspot_information: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str, float]]]], ) -> List[Node]: """Removes such nodes from the list which are not identified as hotspots""" if hotspot_information is None: @@ -945,7 +945,7 @@ def filter_for_hotspots( if len(hotspot_information) == 0: return nodes # collect hotspot information - all_hotspot_descriptions: List[Tuple[int, int, HotspotNodeType, str]] = [] + all_hotspot_descriptions: List[Tuple[int, int, HotspotNodeType, str, float]] = [] for key in hotspot_information: for entry in hotspot_information[key]: all_hotspot_descriptions.append(entry) diff --git a/discopop_library/EmpiricalAutotuning/ArgumentClasses.py b/discopop_library/EmpiricalAutotuning/ArgumentClasses.py new file mode 100644 index 000000000..7392ce682 --- /dev/null +++ b/discopop_library/EmpiricalAutotuning/ArgumentClasses.py @@ -0,0 +1,50 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from dataclasses import dataclass +import logging +import os +from discopop_library.ArgumentClasses.GeneralArguments import GeneralArguments + +logger = logging.getLogger("AutotunerArguments") + + +@dataclass +class AutotunerArguments(GeneralArguments): + """Container Class for the arguments passed to the discopop autotuner""" + + project_path: str + dot_dp_path: str + + def __post_init__(self) -> None: + self.__validate() + + def log(self) -> None: + logger.debug("Arguments:") + for entry in self.__dict__: + logger.debug("-- " + str(entry) + ": " + str(self.__dict__[entry])) + + def __validate(self) -> None: + """Validate the arguments passed to the discopop autotuner, e.g check if given files exist""" + + required_files = [ + self.project_path, + os.path.join(self.project_path, "DP_COMPILE.sh"), + os.path.join(self.project_path, "DP_EXECUTE.sh"), + self.dot_dp_path, + os.path.join(self.dot_dp_path, "FileMapping.txt"), + os.path.join(self.dot_dp_path, "profiler"), + os.path.join(self.dot_dp_path, "explorer"), + os.path.join(self.dot_dp_path, "patch_generator"), + os.path.join(self.dot_dp_path, "hotspot_detection"), + os.path.join(self.dot_dp_path, "hotspot_detection", "Hotspots.json"), + os.path.join(self.dot_dp_path, "line_mapping.json"), + ] + for file in required_files: + if not os.path.exists(file): + raise FileNotFoundError(file) diff --git a/discopop_library/EmpiricalAutotuning/Autotuner.py b/discopop_library/EmpiricalAutotuning/Autotuner.py new file mode 100644 index 000000000..0cc6596de --- /dev/null +++ b/discopop_library/EmpiricalAutotuning/Autotuner.py @@ -0,0 +1,142 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +import logging +import os +from typing import List, Optional, Set, Tuple, cast + +import jsonpickle # type: ignore +from discopop_library.EmpiricalAutotuning.ArgumentClasses import AutotunerArguments +from discopop_library.EmpiricalAutotuning.Classes.CodeConfiguration import CodeConfiguration +from discopop_library.EmpiricalAutotuning.Classes.ExecutionResult import ExecutionResult +from discopop_library.EmpiricalAutotuning.Types import SUGGESTION_ID +from discopop_library.EmpiricalAutotuning.utils import get_applicable_suggestion_ids +from discopop_library.HostpotLoader.HotspotLoaderArguments import HotspotLoaderArguments +from discopop_library.HostpotLoader.HotspotType import HotspotType +from discopop_library.HostpotLoader.hostpot_loader import run as load_hotspots +from discopop_library.result_classes.DetectionResult import DetectionResult + +logger = logging.getLogger("Autotuner") + +configuration_counter = 1 + + +def get_unique_configuration_id() -> int: + global configuration_counter + buffer = configuration_counter + configuration_counter += 1 + return buffer + + +def run(arguments: AutotunerArguments) -> None: + logger.info("Starting discopop autotuner.") + debug_stats: List[Tuple[List[SUGGESTION_ID], float]] = [] + + # get untuned reference result + reference_configuration = CodeConfiguration(arguments.project_path, arguments.dot_dp_path) + reference_configuration.execute(timeout=None) + timeout_after = cast(ExecutionResult, reference_configuration.execution_result).runtime * 2 + debug_stats.append(([], cast(ExecutionResult, reference_configuration.execution_result).runtime)) + + # load hotspots + hsl_arguments = HotspotLoaderArguments( + arguments.log_level, arguments.write_log, False, arguments.dot_dp_path, True, False, True, True, True + ) + hotspot_information = load_hotspots(hsl_arguments) + logger.debug("loaded hotspots") + # load suggestions + with open(os.path.join(arguments.dot_dp_path, "explorer", "detection_result_dump.json"), "r") as f: + tmp_str = f.read() + detection_result: DetectionResult = jsonpickle.decode(tmp_str) + logger.debug("loaded suggestions") + + # greedy search for best suggestion configuration: + # for all hotspot types in descending importance: + visited_configurations: List[List[SUGGESTION_ID]] = [] + best_suggestion_configuration: Tuple[List[SUGGESTION_ID], CodeConfiguration] = ([], reference_configuration) + for hotspot_type in [HotspotType.YES, HotspotType.MAYBE, HotspotType.NO]: + if hotspot_type not in hotspot_information: + continue + # for all loops in descending order by average execution time + loop_tuples = hotspot_information[hotspot_type] + sorted_loop_tuples = sorted(loop_tuples, key=lambda x: x[4], reverse=True) + for loop_tuple in sorted_loop_tuples: + # identify all applicable suggestions for this loop + logger.debug(str(hotspot_type) + " loop: " + str(loop_tuple)) + # create code and execute for all applicable suggestions + applicable_suggestions = get_applicable_suggestion_ids(loop_tuple[0], loop_tuple[1], detection_result) + logger.debug("--> applicable suggestions: " + str(applicable_suggestions)) + suggestion_effects: List[Tuple[List[SUGGESTION_ID], CodeConfiguration]] = [] + for suggestion_id in applicable_suggestions: + current_config = best_suggestion_configuration[0] + [suggestion_id] + if current_config in visited_configurations: + continue + visited_configurations.append(current_config) + tmp_config = reference_configuration.create_copy(get_unique_configuration_id) + tmp_config.apply_suggestions(arguments, current_config) + tmp_config.execute(timeout=timeout_after) + # only consider valid code + if ( + cast(ExecutionResult, tmp_config.execution_result).result_valid + and cast(ExecutionResult, tmp_config.execution_result).return_code == 0 + ): + suggestion_effects.append((current_config, tmp_config)) + debug_stats.append((current_config, cast(ExecutionResult, tmp_config.execution_result).runtime)) + # add current best configuration for reference / to detect "no suggestions is beneficial" + suggestion_effects.append(best_suggestion_configuration) + + logger.debug( + "Suggestion effects:\n" + str([(str(t[0]), str(t[1].execution_result)) for t in suggestion_effects]) + ) + + # select the best option and save it in the current best_configuration + sorted_suggestion_effects = sorted( + suggestion_effects, key=lambda x: cast(ExecutionResult, x[1].execution_result).runtime + ) + buffer = sorted_suggestion_effects[0] + best_suggestion_configuration = buffer + sorted_suggestion_effects = sorted_suggestion_effects[1:] # in preparation of cleanup step + logger.debug( + "Current best configuration: " + + str(best_suggestion_configuration[0]) + + " stored at " + + best_suggestion_configuration[1].root_path + ) + # cleanup other configurations (excluding original version) + logger.debug("Cleanup:") + for _, config in sorted_suggestion_effects: + if config.root_path == reference_configuration.root_path: + continue + config.deleteFolder() + + # continue with the next loop + + # show debug stats + stats_str = "Configuration measurements:\n" + stats_str += "[time]\t[applied suggestions]\n" + for stats in sorted(debug_stats, key=lambda x: x[1], reverse=True): + stats_str += str(round(stats[1], 3)) + "s" + "\t" + str(stats[0]) + "\n" + logger.info(stats_str) + + # calculate result statistics + speedup = ( + cast(ExecutionResult, reference_configuration.execution_result).runtime + / cast(ExecutionResult, best_suggestion_configuration[1].execution_result).runtime + ) + parallel_efficiency = speedup * (1 / cast(int, (0 if os.cpu_count() is None else os.cpu_count()))) + + # show result and statistics + if best_suggestion_configuration[1] is None: + print("No valid configuration found!") + else: + print("##############################") + print("Best configuration located at: " + best_suggestion_configuration[1].root_path) + print("Applied suggestions: " + str(best_suggestion_configuration[0])) + print("Speedup: ", round(speedup, 3)) + print("Parallel efficiency: ", round(parallel_efficiency, 3)) + print("##############################") diff --git a/discopop_library/EmpiricalAutotuning/Classes/CodeConfiguration.py b/discopop_library/EmpiricalAutotuning/Classes/CodeConfiguration.py new file mode 100644 index 000000000..8e9bc4354 --- /dev/null +++ b/discopop_library/EmpiricalAutotuning/Classes/CodeConfiguration.py @@ -0,0 +1,136 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from __future__ import annotations +import logging +import os +import shutil +import subprocess +import time +from typing import Callable, List, Optional +from discopop_library.EmpiricalAutotuning.ArgumentClasses import AutotunerArguments +from discopop_library.EmpiricalAutotuning.Classes.ExecutionResult import ExecutionResult +from discopop_library.EmpiricalAutotuning.Types import SUGGESTION_ID +from discopop_library.PatchApplicator.PatchApplicatorArguments import PatchApplicatorArguments +from discopop_library.PatchApplicator.patch_applicator import run as apply_patches + +logger = logging.getLogger("CodeConfiguration") + + +class CodeConfiguration(object): + root_path: str + config_dot_dp_path: str + execution_result: Optional[ExecutionResult] + + def __init__(self, root_path: str, config_dot_dp_path: str): + self.root_path = root_path + if self.root_path.endswith("/"): + self.root_path = self.root_path[:-1] + self.config_dot_dp_path = config_dot_dp_path + if self.config_dot_dp_path.endswith("/"): + self.config_dot_dp_path = self.config_dot_dp_path[:-1] + self.execution_result = None + logger.debug("Created configuration: " + root_path) + + def __str__(self) -> str: + return self.root_path + + def execute(self, timeout: Optional[float]) -> None: + # create timeout string + timeout_string = "" if timeout is None else "timeout " + str(timeout) + " " + # compile code + logger.info("Compiling configuration: " + str(self)) + compile_result = subprocess.run( + "./DP_COMPILE.sh", cwd=self.root_path, executable="/bin/bash", shell=True, capture_output=True + ) + logger.getChild("compilationOutput").debug(str(compile_result.stdout.decode("utf-8"))) + # execute code + logger.info("Executing configuration: " + str(self) + " with " + timeout_string) + start_time = time.time() + result = subprocess.run( + timeout_string + "./DP_EXECUTE.sh", + cwd=self.root_path, + executable="/bin/bash", + shell=True, + capture_output=True, + ) + logger.getChild("executionOutput").debug(str(result.stdout.decode("utf-8"))) + end_time = time.time() + required_time = end_time - start_time + + # check for result validity + result_valid = True + if os.path.exists(os.path.join(self.root_path, "DP_VALIDATE.sh")): + logger.info("Checking result validity: " + str(self)) + validity_check_result = subprocess.run( + "./DP_VALIDATE.sh", cwd=self.root_path, executable="/bin/bash", shell=True, capture_output=True + ) + logger.getChild("validationOutput").debug(str(validity_check_result.stdout.decode("utf-8"))) + if validity_check_result.returncode != 0: + result_valid = False + + # reporting + logger.debug("Execution took " + str(round(required_time, 4)) + " s") + logger.debug("Execution return code: " + str(result.returncode)) + logger.debug("Execution result valid: " + str(result_valid)) + + self.execution_result = ExecutionResult(required_time, result.returncode, result_valid) + + def create_copy(self, get_new_configuration_id: Callable[[], int]) -> CodeConfiguration: + # create a copy of the project folder + dest_path = self.root_path + "_dpautotune_" + str(get_new_configuration_id()) + if os.path.exists(dest_path): + shutil.rmtree(dest_path) + shutil.copytree(self.root_path, dest_path) + # get updated .discopop folder location + new_dot_discopop_path = self.config_dot_dp_path.replace(self.root_path, dest_path) + logger.debug("Copied folder: " + self.root_path + " to " + dest_path) + logger.debug("Set " + self.config_dot_dp_path + " to " + new_dot_discopop_path) + # update FileMapping.txt in new .discopop folder + with open(os.path.join(new_dot_discopop_path, "NewFileMapping.txt"), "w+") as o: + with open(os.path.join(new_dot_discopop_path, "FileMapping.txt"), "r") as f: + for line in f.readlines(): + line = line.replace(self.root_path, dest_path) + o.write(line) + shutil.move( + os.path.join(new_dot_discopop_path, "NewFileMapping.txt"), + os.path.join(new_dot_discopop_path, "FileMapping.txt"), + ) + logger.debug("Updated " + os.path.join(new_dot_discopop_path, "FileMapping.txt")) + + # create a new CodeConfiguration object + return CodeConfiguration(dest_path, new_dot_discopop_path) + + def deleteFolder(self) -> None: + # delete the root folder. + if not os.path.exists(self.root_path): + raise FileNotFoundError(self.root_path) + shutil.rmtree(self.root_path) + logger.debug("Deleted " + self.root_path) + + def apply_suggestions(self, arguments: AutotunerArguments, suggestion_ids: List[SUGGESTION_ID]) -> None: + """Applies the given suggestion to the code configuration via discopop_patch_applicator""" + sub_logger = logger.getChild("apply_suggestions") + + sub_logger.debug("Applying patch applicator for: " + str(suggestion_ids)) + suggestion_ids_str = [str(id) for id in suggestion_ids] + + save_dir = os.getcwd() + os.chdir(self.config_dot_dp_path) + try: + ret_val = apply_patches( + PatchApplicatorArguments( + arguments.log_level, arguments.write_log, False, suggestion_ids_str, [], False, False, False + ) + ) + sub_logger.debug("Patch applicator return code: " + str(ret_val)) + os.chdir(save_dir) + except Exception as ex: + sub_logger.debug("Got Exception during call to patch applicator.") + os.chdir(save_dir) + raise ex diff --git a/discopop_library/EmpiricalAutotuning/Classes/ExecutionResult.py b/discopop_library/EmpiricalAutotuning/Classes/ExecutionResult.py new file mode 100644 index 000000000..e614e955a --- /dev/null +++ b/discopop_library/EmpiricalAutotuning/Classes/ExecutionResult.py @@ -0,0 +1,23 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + + +class ExecutionResult(object): + runtime: float + return_code: int + result_valid: bool + + def __init__(self, runtime: float, return_code: int, result_valid: bool): + self.runtime = runtime + self.return_code = return_code + self.result_valid = result_valid + + def __str__(self) -> str: + return ( + "" + "time: " + str(self.runtime) + " code: " + str(self.return_code) + " valid: " + str(self.result_valid) + ) diff --git a/discopop_library/EmpiricalAutotuning/Types.py b/discopop_library/EmpiricalAutotuning/Types.py new file mode 100644 index 000000000..53826db30 --- /dev/null +++ b/discopop_library/EmpiricalAutotuning/Types.py @@ -0,0 +1,9 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +SUGGESTION_ID = int diff --git a/discopop_library/EmpiricalAutotuning/__init__.py b/discopop_library/EmpiricalAutotuning/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/discopop_library/EmpiricalAutotuning/__main__.py b/discopop_library/EmpiricalAutotuning/__main__.py new file mode 100644 index 000000000..ef48f32c9 --- /dev/null +++ b/discopop_library/EmpiricalAutotuning/__main__.py @@ -0,0 +1,50 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from argparse import ArgumentParser +import os +from discopop_library.EmpiricalAutotuning.ArgumentClasses import AutotunerArguments +from discopop_library.GlobalLogger.setup import setup_logger +from discopop_library.EmpiricalAutotuning.Autotuner import run + + +def parse_args() -> AutotunerArguments: + """Parse the arguments passed to the discopop autotuner""" + parser = ArgumentParser(description="DiscoPoP Autotuner") + + # fmt: off + + parser.add_argument("--log", type=str, default="WARNING", help="Specify log level: DEBUG, INFO, WARNING, ERROR, CRITICAL") + parser.add_argument("--write-log", action="store_true", help="Create Logfile.") + parser.add_argument("--project-path", type=str, default=os.getcwd(), help="Root path of the project to be tuned. \ + Important: Project root will be copied multiple times! It has to contain the executable scripts DP_COMPILER.sh and DP_EXECUTE.sh! \ + DP_COMPILER.sh must allow the inclusion of OpenMP pragmas into the code. \ + DP_EXECUTE.sh may return not 0, if either the execution or validation of the result failed. \ + A third script DP_VALIDATE.sh might be added to add a validation step, where return code 0 is interpreted as a success, i.e. a valid result.") + parser.add_argument("--dot-dp-path", type=str, default=os.path.join(os.getcwd(), ".discopop"), help="Path to the .discopop folder.") + # fmt: on + + arguments = parser.parse_args() + + return AutotunerArguments( + log_level=arguments.log.upper(), + write_log=arguments.write_log, + project_path=arguments.project_path, + dot_dp_path=arguments.dot_dp_path, + ) + + +def main() -> None: + arguments = parse_args() + setup_logger(arguments) + arguments.log() + run(arguments) + + +if __name__ == "__main__": + main() diff --git a/discopop_library/EmpiricalAutotuning/utils.py b/discopop_library/EmpiricalAutotuning/utils.py new file mode 100644 index 000000000..d86d56706 --- /dev/null +++ b/discopop_library/EmpiricalAutotuning/utils.py @@ -0,0 +1,25 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +import logging +from typing import List + +from discopop_library.EmpiricalAutotuning.Types import SUGGESTION_ID +from discopop_library.result_classes.DetectionResult import DetectionResult + +logger = logging.getLogger("uitls") + + +def get_applicable_suggestion_ids(file_id: int, start_line: int, dtres: DetectionResult) -> List[SUGGESTION_ID]: + """Identify suggestions where start position matches the given start position and return their ids.""" + res: List[int] = [] + for pattern_type in dtres.patterns.__dict__: + for pattern in dtres.patterns.__dict__[pattern_type]: + if pattern.start_line == str(file_id) + ":" + str(start_line) and pattern.applicable_pattern: + res.append(pattern.pattern_id) + return res diff --git a/discopop_library/HostpotLoader/HotspotLoaderArguments.py b/discopop_library/HostpotLoader/HotspotLoaderArguments.py index 1ffa5a056..1f647980a 100644 --- a/discopop_library/HostpotLoader/HotspotLoaderArguments.py +++ b/discopop_library/HostpotLoader/HotspotLoaderArguments.py @@ -16,6 +16,7 @@ class HotspotLoaderArguments(GeneralArguments): """Container Class for the arguments passed to the hotspot loader""" verbose: bool + dot_discopop_path: str get_loops: bool get_functions: bool get_YES: bool diff --git a/discopop_library/HostpotLoader/hostpot_loader.py b/discopop_library/HostpotLoader/hostpot_loader.py index 484ad5be7..5520be873 100644 --- a/discopop_library/HostpotLoader/hostpot_loader.py +++ b/discopop_library/HostpotLoader/hostpot_loader.py @@ -18,36 +18,33 @@ FILEID = int STARTLINE = int NAME = str +AVERAGE_RUNTIME = float -def run(arguments: HotspotLoaderArguments) -> Dict[HotspotType, List[Tuple[FILEID, STARTLINE, HotspotNodeType, NAME]]]: +def run( + arguments: HotspotLoaderArguments, +) -> Dict[HotspotType, List[Tuple[FILEID, STARTLINE, HotspotNodeType, NAME, AVERAGE_RUNTIME]]]: """Loads Hotspots for processing in other tools of the framework""" - if arguments.verbose: - print("HotspotLoader - Configuration:") - print(arguments) logger = logging.getLogger("HotspotLoader") - logger.info("LOADING HOTSPOTS") - result_dict: Dict[HotspotType, List[Tuple[FILEID, STARTLINE, HotspotNodeType, NAME]]] = dict() + dot_discopop_path = arguments.dot_discopop_path if len(arguments.dot_discopop_path) > 0 else os.getcwd() - if not os.path.exists(os.path.join(os.getcwd(), "hotspot_detection")): + result_dict: Dict[HotspotType, List[Tuple[FILEID, STARTLINE, HotspotNodeType, NAME, AVERAGE_RUNTIME]]] = dict() + + if not os.path.exists(os.path.join(dot_discopop_path, "hotspot_detection")): return result_dict - if not os.path.exists(os.path.join(os.getcwd(), "hotspot_detection", "Hotspots.json")): + if not os.path.exists(os.path.join(dot_discopop_path, "hotspot_detection", "Hotspots.json")): return result_dict - with open(os.path.join(os.getcwd(), "hotspot_detection", "Hotspots.json"), "r") as f: + with open(os.path.join(dot_discopop_path, "hotspot_detection", "Hotspots.json"), "r") as f: hotspots = json.load(f) - print("HOTSPOTS: ") for key in hotspots: - print("->", key) for entry in hotspots[key]: - print("\t->", entry) # check if hotness is considered if entry["hotness"] in arguments.get_considered_hotness(): # check if type is considered if entry["typ"] in arguments.get_considered_types(): - print("\tCONSIDER") if get_HotspotType_from_string(entry["hotness"]) not in result_dict: result_dict[get_HotspotType_from_string(entry["hotness"])] = [] @@ -57,8 +54,8 @@ def run(arguments: HotspotLoaderArguments) -> Dict[HotspotType, List[Tuple[FILEI int(entry["lineNum"]), get_HotspotNodeType_from_string(entry["typ"]), entry["name"], + float(entry["avr"]), ) ) - print("LOADED: ") - print(result_dict) + logger.info("Loaded hotspots:\n" + str(result_dict)) return result_dict diff --git a/discopop_library/discopop_optimizer/PETParser/PETParser.py b/discopop_library/discopop_optimizer/PETParser/PETParser.py index 8c37b3d17..eeff36f62 100644 --- a/discopop_library/discopop_optimizer/PETParser/PETParser.py +++ b/discopop_library/discopop_optimizer/PETParser/PETParser.py @@ -630,7 +630,7 @@ def __remove_non_hotspot_function_bodys(self) -> None: return all_hotspot_functions_raw: List[Tuple[int, str]] = [] for key in self.experiment.hotspot_functions: - for file_id, line_num, hs_node_type, name in self.experiment.hotspot_functions[key]: + for file_id, line_num, hs_node_type, name, _ in self.experiment.hotspot_functions[key]: if hs_node_type == HotspotNodeType.FUNCTION: all_hotspot_functions_raw.append((file_id, name)) diff --git a/discopop_library/discopop_optimizer/Variables/Experiment.py b/discopop_library/discopop_optimizer/Variables/Experiment.py index 85c66e166..8381e9be9 100644 --- a/discopop_library/discopop_optimizer/Variables/Experiment.py +++ b/discopop_library/discopop_optimizer/Variables/Experiment.py @@ -78,7 +78,7 @@ class Experiment(object): node_id_to_suggestion_dict: Dict[int, int] pattern_id_to_decisions_dict: Dict[int, List[int]] - hotspot_functions: Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]] + hotspot_functions: Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str, float]]] hotspot_function_node_ids: List[int] profile: Optional[Profile] @@ -90,7 +90,7 @@ def __init__( detection_result: DetectionResult, profiler_dir: str, arguments: OptimizerArguments, - hotspot_functions: Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]], + hotspot_functions: Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str, float]]], ): self.__system = system self.detection_result = detection_result diff --git a/discopop_library/discopop_optimizer/optimizer.py b/discopop_library/discopop_optimizer/optimizer.py index adcb0b952..4ad84bee7 100644 --- a/discopop_library/discopop_optimizer/optimizer.py +++ b/discopop_library/discopop_optimizer/optimizer.py @@ -125,6 +125,7 @@ def run_passive_optimizer(arguments: OptimizerArguments) -> None: hotspot_functions = load_hotspots( HotspotLoaderArguments( verbose=arguments.verbose, + dot_discopop_path=os.getcwd(), get_loops=False, get_functions=True, get_YES=True, diff --git a/docs/tools/Autotuner.md b/docs/tools/Autotuner.md new file mode 100644 index 000000000..110ce1c97 --- /dev/null +++ b/docs/tools/Autotuner.md @@ -0,0 +1,41 @@ +--- +layout: default +title: Empirical autotuner +parent: Tools +nav_order: 7 +--- + +# DiscoPoP Empirical Autotuner +## Executable +`discopop_auto_tuner` + +## Purpose +Identify the best configuration of parallel code which is achievable by applying a combination of the parallelization suggestion found by the [DiscoPoP Explorer](../tools/Explorer.md) or [optimizer](../tools/Optimizer.md). Internally, the [DiscoPoP patch applicator](../tools/Patch_applicator.md) is used to create different parallel codes, which will be compiled, executed, and evaluated based on the observed execution time and result validity. +To find a beneficial configuration in a comparatively short amount of time, a greedy search is performed as described in the following. +- Initialize the "best_configuration" as the sequential code +- Focus on identified hotspots, followed by code regions which might be hotspots, and lastly coldspots +- Sort the loops in each category in descending order by their average runtime, thus focusing on "more important" loops wrt. execution time first +- For each loop, create a parallel version of the code for each suggestion applicable to this loop +- Compile the parallel code, execute, and verify it. +- Select the best parallel code and and save it as the new best_configuration +- Continue with the next loop, and successively hotspot category + +## Required input +- `Parallel patterns` in the form of a `JSON` file, created by the [Explorer](Explorer.md) +- `Detected hotspots` in the form of a `JSON` file, created by the [Hotspot detection](https://github.com/discopop-project/Hotspot-Detection) +- `Prepared patch files` created by the [DiscoPoP patch generator](Patch_generator.md) +- `DP_COMPILE.sh`, `DP_EXECUTE.sh`, and optionally `DP_VALIDATE.sh` scripts to compile, execute and validate the results of the created parallel code. + +## Output +The parallel code representing the identified best configuration will be stored in a copy of the project directory. +Information on the configuration can be found in the included `.discopop` directory. + +## Limitations +Due to the empirical nature of the optimization approach described above, varying sets of input data might yield differing selected configurations. +For this reason it is important, that the used input data (typically specified in `DP_EXECUTE.sh`) is representative for a production run of the software and large enough to allow for beneficial parallelizations. + +## Note +For a more detailed description of the available run-time arguments, please refer to the help string of the respective tool. +``` +discopop_auto_tuner --help +``` diff --git a/docs/tools/Scripts_and_wrappers.md b/docs/tools/Scripts_and_wrappers.md index e39b96392..065de61fa 100644 --- a/docs/tools/Scripts_and_wrappers.md +++ b/docs/tools/Scripts_and_wrappers.md @@ -2,7 +2,7 @@ layout: default title: Scripts and wrappers parent: Tools -nav_order: 6 +nav_order: 8 --- # Scripts and wrappers diff --git a/docs/tools/organization_chart.graphml b/docs/tools/organization_chart.graphml index e89ebc92c..c4c35ef7a 100644 --- a/docs/tools/organization_chart.graphml +++ b/docs/tools/organization_chart.graphml @@ -1,6 +1,6 @@ - + @@ -168,6 +168,27 @@ CXX=build/scripts/CXX_wrapper.sh + + + + + + Autotuner + + + + + + + + + + Tuned +parallel code + + + @@ -341,10 +362,44 @@ CXX=build/scripts/CXX_wrapper.sh - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/tools/organization_chart.svg b/docs/tools/organization_chart.svg index ea9738b61..f0d45ce6c 100644 --- a/docs/tools/organization_chart.svg +++ b/docs/tools/organization_chart.svg @@ -1,4 +1,4 @@ - + @@ -63,15 +63,23 @@ + + + + + + + + - + - + - + @@ -79,7 +87,7 @@ Instrumented - sequential + sequential executable @@ -182,6 +190,21 @@ Sequential code + + + + + + Autotuner + + + + + + + Tuned + parallel code + @@ -205,7 +228,7 @@ - + @@ -220,6 +243,15 @@ + + + + + + + + + diff --git a/setup.py b/setup.py index 702dc1129..0f520690a 100644 --- a/setup.py +++ b/setup.py @@ -63,6 +63,7 @@ "discopop_patch_generator=discopop_library.PatchGenerator.__main__:main", "discopop_patch_applicator=discopop_library.PatchApplicator.__main__:main", "discopop_config_provider=discopop_library.ConfigProvider.__main__:main", + "discopop_auto_tuner=discopop_library.EmpiricalAutotuning.__main__:main" ] }, zip_safe=True, From 1fc2fef12ebdf8ad51215c8b053de11c3fb07a7b Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Thu, 18 Jul 2024 07:58:01 +0200 Subject: [PATCH 030/105] fix(autotuner): delete invalid code during cleanup --- discopop_library/EmpiricalAutotuning/Autotuner.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/discopop_library/EmpiricalAutotuning/Autotuner.py b/discopop_library/EmpiricalAutotuning/Autotuner.py index 0cc6596de..735002fd4 100644 --- a/discopop_library/EmpiricalAutotuning/Autotuner.py +++ b/discopop_library/EmpiricalAutotuning/Autotuner.py @@ -87,6 +87,9 @@ def run(arguments: AutotunerArguments) -> None: ): suggestion_effects.append((current_config, tmp_config)) debug_stats.append((current_config, cast(ExecutionResult, tmp_config.execution_result).runtime)) + else: + # delete invalid code + tmp_config.deleteFolder() # add current best configuration for reference / to detect "no suggestions is beneficial" suggestion_effects.append(best_suggestion_configuration) From 6d23e8a9909df2052a3763c0dbb3abdc81d5964f Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Mon, 22 Jul 2024 16:19:38 +0200 Subject: [PATCH 031/105] Tests and fixes for detection of data sharing clauses (#641) * tests(clauses): no-clauses * add test: private clause * add test: shared clause * minor improvements * add test: firstprivate clause * add test: lastprivate clause * add tests * fix: data sharing clauses for stack variables * fix(explorer)[clauses]: tests: first_private case 1 + private case 1 * test(explorer)[clauses]: add wip_end_to_end tests * fix: add missing utilities --- DiscoPoP/DiscoPoP.hpp | 4 +- DiscoPoP/hybrid_analysis/InstructionDG.cpp | 21 +- DiscoPoP/hybrid_analysis/InstructionDG.hpp | 9 + DiscoPoP/llvm_hooks/runOnFunction.cpp | 64 +- discopop_explorer/utils.py | 32 +- rtlib/calltree/utils.cpp | 2 +- rtlib/calltree/utils.hpp | 2 +- rtlib/loop/LoopManager.hpp | 21 +- rtlib/loop/LoopTableEntry.hpp | 10 +- rtlib/runtimeFunctions.cpp | 38 +- .../src/FileMapping.txt | 1 - .../above_nesting_level_3/src/FileMapping.txt | 1 - .../calls/above_nesting_level_3/src/code.ll | 855 ------------------ .../do_all/calls/allowing/src/FileMapping.txt | 1 - .../do_all/calls/allowing/src/code.ll | 552 ----------- .../positive/simple_1/src/FileMapping.txt | 1 - .../negative/case_1/src/FileMapping.txt | 1 - .../negative/case_1/src/code.ll | 427 --------- .../OMPSCR/c_Mandelbrot/src/FileMapping.txt | 1 - test/end_to_end/sharing_clauses/__init__.py | 0 .../sharing_clauses/do_all/__init__.py | 0 .../do_all/first_private/__init__.py | 0 .../do_all/first_private/case_1/__init__.py | 0 .../do_all/first_private/case_1/src/Makefile | 15 + .../do_all/first_private/case_1/src/code.cpp | 14 + .../do_all/first_private/case_1/test.py | 82 ++ .../do_all/last_private/__init__.py | 0 .../do_all/last_private/case_1/__init__.py | 0 .../do_all/last_private/case_1/src/Makefile | 15 + .../do_all/last_private/case_1/src/code.cpp | 14 + .../do_all/last_private/case_1/test.py | 82 ++ .../do_all/no_clause/__init__.py | 0 .../do_all/no_clause/case_1/__init__.py | 0 .../do_all/no_clause/case_1/src/Makefile | 17 + .../do_all/no_clause/case_1/src/code.cpp | 11 + .../do_all/no_clause/case_1/test.py | 82 ++ .../do_all/private/__init__.py | 0 .../do_all/private/case_1/__init__.py | 0 .../do_all/private/case_1/src/Makefile | 15 + .../do_all/private/case_1/src/code.cpp | 15 + .../do_all/private/case_1/test.py | 82 ++ .../sharing_clauses/do_all/shared/__init__.py | 0 .../do_all/shared/case_1/__init__.py | 0 .../do_all/shared/case_1/src/Makefile | 15 + .../do_all/shared/case_1/src/code.cpp | 17 + .../do_all/shared/case_1/test.py | 82 ++ .../do_all/shared/case_2/__init__.py | 0 .../do_all/shared/case_2/src/Makefile | 15 + .../do_all/shared/case_2/src/code.cpp | 16 + .../do_all/shared/case_2/test.py | 82 ++ .../do_all/shared/case_3/__init__.py | 0 .../do_all/shared/case_3/src/Makefile | 15 + .../do_all/shared/case_3/src/code.cpp | 16 + .../do_all/shared/case_3/test.py | 82 ++ test/utils/sharing_clauses/__init__.py | 0 test/utils/sharing_clauses/clauses_utils.py | 42 + .../sharing_clauses/__init__.py | 0 .../sharing_clauses/do_all/__init__.py | 0 .../do_all/first_private/__init__.py | 0 .../do_all/first_private/case_2/__init__.py | 0 .../do_all/first_private/case_2/src/Makefile | 15 + .../do_all/first_private/case_2/src/code.cpp | 16 + .../do_all/first_private/case_2/test.py | 82 ++ .../do_all/private/__init__.py | 0 .../do_all/private/case_2/__init__.py | 0 .../do_all/private/case_2/src/Makefile | 15 + .../do_all/private/case_2/src/code.cpp | 16 + .../do_all/private/case_2/test.py | 82 ++ 68 files changed, 1209 insertions(+), 1886 deletions(-) delete mode 100644 test/end_to_end/do_all/backwards_array_access/src/FileMapping.txt delete mode 100644 test/end_to_end/do_all/calls/above_nesting_level_3/src/FileMapping.txt delete mode 100644 test/end_to_end/do_all/calls/above_nesting_level_3/src/code.ll delete mode 100644 test/end_to_end/do_all/calls/allowing/src/FileMapping.txt delete mode 100644 test/end_to_end/do_all/calls/allowing/src/code.ll delete mode 100644 test/end_to_end/optimizer/loop_collapse/positive/simple_1/src/FileMapping.txt delete mode 100644 test/end_to_end/reduction_pattern/negative/case_1/src/FileMapping.txt delete mode 100644 test/end_to_end/reduction_pattern/negative/case_1/src/code.ll delete mode 100644 test/end_to_end/reduction_pattern/positive/nested/OMPSCR/c_Mandelbrot/src/FileMapping.txt create mode 100644 test/end_to_end/sharing_clauses/__init__.py create mode 100644 test/end_to_end/sharing_clauses/do_all/__init__.py create mode 100644 test/end_to_end/sharing_clauses/do_all/first_private/__init__.py create mode 100644 test/end_to_end/sharing_clauses/do_all/first_private/case_1/__init__.py create mode 100644 test/end_to_end/sharing_clauses/do_all/first_private/case_1/src/Makefile create mode 100644 test/end_to_end/sharing_clauses/do_all/first_private/case_1/src/code.cpp create mode 100644 test/end_to_end/sharing_clauses/do_all/first_private/case_1/test.py create mode 100644 test/end_to_end/sharing_clauses/do_all/last_private/__init__.py create mode 100644 test/end_to_end/sharing_clauses/do_all/last_private/case_1/__init__.py create mode 100644 test/end_to_end/sharing_clauses/do_all/last_private/case_1/src/Makefile create mode 100644 test/end_to_end/sharing_clauses/do_all/last_private/case_1/src/code.cpp create mode 100644 test/end_to_end/sharing_clauses/do_all/last_private/case_1/test.py create mode 100644 test/end_to_end/sharing_clauses/do_all/no_clause/__init__.py create mode 100644 test/end_to_end/sharing_clauses/do_all/no_clause/case_1/__init__.py create mode 100644 test/end_to_end/sharing_clauses/do_all/no_clause/case_1/src/Makefile create mode 100644 test/end_to_end/sharing_clauses/do_all/no_clause/case_1/src/code.cpp create mode 100644 test/end_to_end/sharing_clauses/do_all/no_clause/case_1/test.py create mode 100644 test/end_to_end/sharing_clauses/do_all/private/__init__.py create mode 100644 test/end_to_end/sharing_clauses/do_all/private/case_1/__init__.py create mode 100644 test/end_to_end/sharing_clauses/do_all/private/case_1/src/Makefile create mode 100644 test/end_to_end/sharing_clauses/do_all/private/case_1/src/code.cpp create mode 100644 test/end_to_end/sharing_clauses/do_all/private/case_1/test.py create mode 100644 test/end_to_end/sharing_clauses/do_all/shared/__init__.py create mode 100644 test/end_to_end/sharing_clauses/do_all/shared/case_1/__init__.py create mode 100644 test/end_to_end/sharing_clauses/do_all/shared/case_1/src/Makefile create mode 100644 test/end_to_end/sharing_clauses/do_all/shared/case_1/src/code.cpp create mode 100644 test/end_to_end/sharing_clauses/do_all/shared/case_1/test.py create mode 100644 test/end_to_end/sharing_clauses/do_all/shared/case_2/__init__.py create mode 100644 test/end_to_end/sharing_clauses/do_all/shared/case_2/src/Makefile create mode 100644 test/end_to_end/sharing_clauses/do_all/shared/case_2/src/code.cpp create mode 100644 test/end_to_end/sharing_clauses/do_all/shared/case_2/test.py create mode 100644 test/end_to_end/sharing_clauses/do_all/shared/case_3/__init__.py create mode 100644 test/end_to_end/sharing_clauses/do_all/shared/case_3/src/Makefile create mode 100644 test/end_to_end/sharing_clauses/do_all/shared/case_3/src/code.cpp create mode 100644 test/end_to_end/sharing_clauses/do_all/shared/case_3/test.py create mode 100644 test/utils/sharing_clauses/__init__.py create mode 100644 test/utils/sharing_clauses/clauses_utils.py create mode 100644 test/wip_end_to_end/sharing_clauses/__init__.py create mode 100644 test/wip_end_to_end/sharing_clauses/do_all/__init__.py create mode 100644 test/wip_end_to_end/sharing_clauses/do_all/first_private/__init__.py create mode 100644 test/wip_end_to_end/sharing_clauses/do_all/first_private/case_2/__init__.py create mode 100644 test/wip_end_to_end/sharing_clauses/do_all/first_private/case_2/src/Makefile create mode 100644 test/wip_end_to_end/sharing_clauses/do_all/first_private/case_2/src/code.cpp create mode 100644 test/wip_end_to_end/sharing_clauses/do_all/first_private/case_2/test.py create mode 100644 test/wip_end_to_end/sharing_clauses/do_all/private/__init__.py create mode 100644 test/wip_end_to_end/sharing_clauses/do_all/private/case_2/__init__.py create mode 100644 test/wip_end_to_end/sharing_clauses/do_all/private/case_2/src/Makefile create mode 100644 test/wip_end_to_end/sharing_clauses/do_all/private/case_2/src/code.cpp create mode 100644 test/wip_end_to_end/sharing_clauses/do_all/private/case_2/test.py diff --git a/DiscoPoP/DiscoPoP.hpp b/DiscoPoP/DiscoPoP.hpp index 44c32d111..1d846147e 100644 --- a/DiscoPoP/DiscoPoP.hpp +++ b/DiscoPoP/DiscoPoP.hpp @@ -71,14 +71,14 @@ #define DP_DEBUG false #define ClCheckLoopPar true -#define DumpToDot false +#define DumpToDot true #define DP_BRANCH_TRACKING \ true // toggles the creation of instrumentation calls for tracking taken // branches. Required by the graph pruning step of the DiscoPoP // optimizer. #define DP_DEBUG false #define DP_VERBOSE false // prints warning messages -#define DP_hybrid_DEBUG false +#define DP_hybrid_DEBUG true using namespace llvm; using namespace std; diff --git a/DiscoPoP/hybrid_analysis/InstructionDG.cpp b/DiscoPoP/hybrid_analysis/InstructionDG.cpp index 36ebfad3e..2f6b0d5be 100644 --- a/DiscoPoP/hybrid_analysis/InstructionDG.cpp +++ b/DiscoPoP/hybrid_analysis/InstructionDG.cpp @@ -64,7 +64,7 @@ void InstructionDG::recursiveDepFinder(set *checkedInstructions, void InstructionDG::highlightInstructionNode(Instruction *instr) { highlightedInstructionNodes.insert(instr); } -string getInstructionLine(Instruction *I) { +string InstructionDG::getInstructionLine(Instruction *I) { if (DebugLoc dl = I->getDebugLoc()) { return to_string(dl->getLine()); } else { @@ -72,6 +72,25 @@ string getInstructionLine(Instruction *I) { } } +bool InstructionDG::edgeIsINIT(Edge *e){ + Instruction *I = e->getSrc()->getItem(); + Instruction *J = e->getDst()->getItem(); + + if(isa(J)){ + return true; + } + return false; +} + +string InstructionDG::getInitEdgeInstructionLine(Edge *e){ + return getInstructionLine(e->getSrc()->getItem()); +} + +string InstructionDG::getValueNameAndMemRegIDFromEdge(Edge *e, unordered_map> &staticValueNameToMemRegIDMap){ + Instruction *I = e->getSrc()->getItem(); + return staticValueNameToMemRegIDMap[VNF->getVarName(I)].first + "(" + staticValueNameToMemRegIDMap[VNF->getVarName(I)].second + ")"; +} + string InstructionDG::edgeToDPDep(Edge *e, unordered_map> &staticValueNameToMemRegIDMap) { // staticValueNameToMemRegIDMap maps: TO (original diff --git a/DiscoPoP/hybrid_analysis/InstructionDG.hpp b/DiscoPoP/hybrid_analysis/InstructionDG.hpp index 785e65443..2262fef0f 100644 --- a/DiscoPoP/hybrid_analysis/InstructionDG.hpp +++ b/DiscoPoP/hybrid_analysis/InstructionDG.hpp @@ -32,9 +32,18 @@ class InstructionDG : public Graph { public: InstructionDG(dputil::VariableNameFinder *_VNF, InstructionCFG *_CFG, int32_t _fid); + bool edgeIsINIT(Edge *e); + string edgeToDPDep(Edge *e, unordered_map> &staticValueNameToMemRegIDMap); void highlightInstructionNode(Instruction *instr); void dumpToDot(const string targetPath); + + string getInstructionLine(Instruction *I); + + string getInitEdgeInstructionLine(Edge *e); + + string getValueNameAndMemRegIDFromEdge(Edge *e, unordered_map> &staticValueNameToMemRegIDMap); + }; diff --git a/DiscoPoP/llvm_hooks/runOnFunction.cpp b/DiscoPoP/llvm_hooks/runOnFunction.cpp index 571d47f50..97283df47 100644 --- a/DiscoPoP/llvm_hooks/runOnFunction.cpp +++ b/DiscoPoP/llvm_hooks/runOnFunction.cpp @@ -276,6 +276,25 @@ bool DiscoPoP::runOnFunction(Function &F) { InstructionCFG CFG(VNF, F); InstructionDG DG(VNF, &CFG, fid); + // collect init instruction to prevent false-positive WAW Dependences due to allocations in loops, + // which will be moved to the function entry + map> lineToInitializedVarsMap; + for (auto edge : DG.getEdges()){ + if(DG.edgeIsINIT(edge)){ + string initLine = DG.getInitEdgeInstructionLine(edge); + string varIdentifier = DG.getValueNameAndMemRegIDFromEdge(edge, staticValueNameToMemRegIDMap); + std::cout << "Found init: " << DG.edgeToDPDep(edge, staticValueNameToMemRegIDMap) << "\n"; + std::cout << "\t@ " << initLine << "\n"; + std::cout << "\tvar: " << varIdentifier << "\n"; + + if(lineToInitializedVarsMap.find(initLine) == lineToInitializedVarsMap.end()){ + set tmp; + lineToInitializedVarsMap[initLine] = tmp; + } + lineToInitializedVarsMap[initLine].insert(varIdentifier); + } + } + for (auto edge : DG.getEdges()) { Instruction *Src = edge->getSrc()->getItem(); Instruction *Dst = edge->getDst()->getItem(); @@ -291,19 +310,62 @@ bool DiscoPoP::runOnFunction(Function &F) { if (!conditionalBBDepMap.count(Src->getParent())) { set tmp; conditionalBBDepMap[Src->getParent()] = tmp; + + std::cout<< "Registered set1: \n"; + for(auto s : tmp){ + std::cout << "--> " << s << "\n"; + } } conditionalBBDepMap[Src->getParent()].insert(DG.edgeToDPDep(edge, staticValueNameToMemRegIDMap)); + std::cout << "Inserted1: " << DG.edgeToDPDep(edge, staticValueNameToMemRegIDMap) << "\n"; } else { if (!conditionalBBPairDepMap.count(Dst->getParent())) { map> tmp; conditionalBBPairDepMap[Dst->getParent()] = tmp; + std::cout<< "Registered set2: \n"; + for(auto pair : tmp){ + for(auto s : pair.second){ + std::cout << "--> " << s << "\n"; + } + } } if (!conditionalBBPairDepMap[Dst->getParent()].count(Src->getParent())) { set tmp; conditionalBBPairDepMap[Dst->getParent()][Src->getParent()] = tmp; + std::cout<< "Registered set3: \n"; + for(auto s : tmp){ + std::cout << "--> " << s << "\n"; + } } - conditionalBBPairDepMap[Dst->getParent()][Src->getParent()].insert( + std::cout << "First: " << Dst << "\n"; + Dst->print(outs()); + std::cout << "\n"; + std::cout << "Second: " << Src << "\n"; + Src->print(outs()); + std::cout << "\n"; + // Prevent reporting of false-positive WAW Dependencies due to alloca movement from e.g. loops to function entry + bool insertDep = true; + if(Dst == Src){ // check if instruciton are the same + std::cout << "==> Potential for false-positive WAW\n"; + std::cout << "--> same inst\n"; + // check if initialization exists in the instruction line + if(lineToInitializedVarsMap.find(DG.getInstructionLine(Dst)) != lineToInitializedVarsMap.end()){ + std::cout << "--> same init exists\n"; + // check if the accessed variable is initialed here + string varIdentifier = DG.getValueNameAndMemRegIDFromEdge(edge, staticValueNameToMemRegIDMap); + if(lineToInitializedVarsMap[DG.getInstructionLine(Dst)].find(varIdentifier) != lineToInitializedVarsMap[DG.getInstructionLine(Dst)].end()){ + // ignore this access as the initialized variable is accessed + std::cout << "==> initialized var accessed\n"; + insertDep = false; + } + } + } + + if(insertDep){ + conditionalBBPairDepMap[Dst->getParent()][Src->getParent()].insert( DG.edgeToDPDep(edge, staticValueNameToMemRegIDMap)); + std::cout << "Inserted: " << DG.edgeToDPDep(edge, staticValueNameToMemRegIDMap) << "\n"; + } } omittableInstructions.insert(Src); omittableInstructions.insert(Dst); diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index 8f721d028..146aab72f 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -410,6 +410,13 @@ def is_first_written( break if not res: return False + + # catch potential false-positives if len(war) == 0 + if len(war) == 0: + for eraw in raw: + if eraw[2].memory_region in mem_regs and eraw[1] not in [n.id for n in sub]: + # value written prior to loop is read --> can not be first written + return False return True @@ -703,19 +710,26 @@ def classify_loop_variables( # array type variable is written shared.append(var) else: - private.append(var) + if is_first_written(vars[var], raw, waw, sub): + private.append(var) + else: + first_private.append(var) elif is_first_written(vars[var], raw, war, sub): - if is_read_in_subtree(vars[var], rev_raw, rst): - if is_scalar_val(var): - last_private.append(var) - else: - shared.append(var) + if len(vars[var].intersection(initialized_memory_regions)) > 0: + # variable is initialized in loop. No data sharing clauses required. + pass else: - if is_scalar_val(var): - private.append(var) + if is_read_in_subtree(vars[var], rev_raw, rst): + if is_scalar_val(var): + last_private.append(var) + else: + shared.append(var) else: - shared.append(var) + if is_scalar_val(var): + private.append(var) + else: + shared.append(var) # return first_private, private, last_private, shared, reduction return ( sorted(first_private), diff --git a/rtlib/calltree/utils.cpp b/rtlib/calltree/utils.cpp index b4f2924a9..7293112b2 100644 --- a/rtlib/calltree/utils.cpp +++ b/rtlib/calltree/utils.cpp @@ -17,7 +17,7 @@ namespace __dp { -DependencyMetadata processQueueElement(MetaDataQueueElement && mdqe) { +DependencyMetadata processQueueElement(MetaDataQueueElement &&mdqe) { const auto calltree_timer = Timer(timers, TimerRegion::PROCESSQUEUEELEMENT); // cout << "processing " << mdqe.toString() << "\n"; diff --git a/rtlib/calltree/utils.hpp b/rtlib/calltree/utils.hpp index 809190cf2..df33045b5 100644 --- a/rtlib/calltree/utils.hpp +++ b/rtlib/calltree/utils.hpp @@ -14,5 +14,5 @@ #include "MetaDataQueueElement.hpp" namespace __dp { -DependencyMetadata processQueueElement(MetaDataQueueElement && mdqe); +DependencyMetadata processQueueElement(MetaDataQueueElement &&mdqe); } // namespace __dp diff --git a/rtlib/loop/LoopManager.hpp b/rtlib/loop/LoopManager.hpp index dd4cc176a..5be830b1d 100644 --- a/rtlib/loop/LoopManager.hpp +++ b/rtlib/loop/LoopManager.hpp @@ -36,11 +36,11 @@ class LoopManager { #if DP_CALLTREE_PROFILING // check if dependency metadata calculation should be disabled due to inheritance bool inherited_dep_metadata_calculation = true; - if (! loopStack.empty()){ + if (!loopStack.empty()) { inherited_dep_metadata_calculation = loopStack.top().get_dependency_metadata_calculation_enabled(); } - -#endif + +#endif loopStack.push(LoopTableEntry(function_level, loop_id, 0, begin_line)); #if DP_CALLTREE_PROFILING // set the inherited metadata calculation flag @@ -60,20 +60,23 @@ class LoopManager { } #if DP_CALLTREE_PROFILING - bool enable_calculate_dependency_metadata() { - return loopStack.top().get_dependency_metadata_calculation_enabled(); - }; + bool enable_calculate_dependency_metadata() { return loopStack.top().get_dependency_metadata_calculation_enabled(); }; #endif void iterate_loop(const std::int32_t function_level) { loopStack.increment_top_count(); #if DP_CALLTREE_PROFILING - if(! DP_CALLTREE_PROFILING_METADATA_CUTOFF == 0){ + if (!DP_CALLTREE_PROFILING_METADATA_CUTOFF == 0) { #if DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY - loopStack.non_const_top().set_dependency_metadata_calculation_enabled((loopStack.top().get_dependency_metadata_calculation_enabled() && (DP_CALLTREE_PROFILING_METADATA_CUTOFF > loopStack.top().get_count())) || ((rand() % 1000) < DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY)); + loopStack.non_const_top().set_dependency_metadata_calculation_enabled( + (loopStack.top().get_dependency_metadata_calculation_enabled() && + (DP_CALLTREE_PROFILING_METADATA_CUTOFF > loopStack.top().get_count())) || + ((rand() % 1000) < DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY)); #else // DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY is 0 - loopStack.non_const_top().set_dependency_metadata_calculation_enabled(loopStack.top().get_dependency_metadata_calculation_enabled() && (DP_CALLTREE_PROFILING_METADATA_CUTOFF > loopStack.top().get_count())); + loopStack.non_const_top().set_dependency_metadata_calculation_enabled( + loopStack.top().get_dependency_metadata_calculation_enabled() && + (DP_CALLTREE_PROFILING_METADATA_CUTOFF > loopStack.top().get_count())); #endif } #endif diff --git a/rtlib/loop/LoopTableEntry.hpp b/rtlib/loop/LoopTableEntry.hpp index a32e4ba41..c7867b2ff 100644 --- a/rtlib/loop/LoopTableEntry.hpp +++ b/rtlib/loop/LoopTableEntry.hpp @@ -25,7 +25,7 @@ struct LoopTableEntry { #if DP_CALLTREE_PROFILING dependency_metadata_calculation_enabled = true; #endif - } + } std::int32_t funcLevel; std::int32_t loopID; @@ -42,13 +42,9 @@ struct LoopTableEntry { void increment_count() noexcept { ++count; } #if DP_CALLTREE_PROFILING - void set_dependency_metadata_calculation_enabled(bool value){ - dependency_metadata_calculation_enabled = value; - } + void set_dependency_metadata_calculation_enabled(bool value) { dependency_metadata_calculation_enabled = value; } - bool get_dependency_metadata_calculation_enabled() const { - return dependency_metadata_calculation_enabled; - } + bool get_dependency_metadata_calculation_enabled() const { return dependency_metadata_calculation_enabled; } #endif private: diff --git a/rtlib/runtimeFunctions.cpp b/rtlib/runtimeFunctions.cpp index 462c9799e..371790ffb 100644 --- a/rtlib/runtimeFunctions.cpp +++ b/rtlib/runtimeFunctions.cpp @@ -59,7 +59,8 @@ namespace __dp { #if DP_CALLTREE_PROFILING void addDep(depType type, LID curr, LID depOn, const char *var, string AAvar, ADDR addr, std::unordered_map> *thread_private_write_addr_to_call_tree_node_map, - std::unordered_map> *thread_private_read_addr_to_call_tree_node_map, bool calculate_dependency_metadata) { + std::unordered_map> *thread_private_read_addr_to_call_tree_node_map, + bool calculate_dependency_metadata) { #else void addDep(depType type, LID curr, LID depOn, const char *var, string AAvar, ADDR addr) { #endif @@ -91,12 +92,13 @@ void addDep(depType type, LID curr, LID depOn, const char *var, string AAvar, AD #if DP_CALLTREE_PROFILING // register dependency for call_tree based metadata calculation - if(calculate_dependency_metadata){ + if (calculate_dependency_metadata) { DependencyMetadata dmd; switch (type) { case RAW: // register metadata calculation - // cout << "Register metadata calculation: RAW " << decodeLID(curr) << " " << decodeLID(depOn) << " " << var << " (" + // cout << "Register metadata calculation: RAW " << decodeLID(curr) << " " << decodeLID(depOn) << " " << var << " + // (" // << (*thread_private_write_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << // (*thread_private_write_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ") " << " (" << // (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << @@ -104,8 +106,8 @@ void addDep(depType type, LID curr, LID depOn, const char *var, string AAvar, AD // process directly dmd = processQueueElement(MetaDataQueueElement(type, curr, depOn, var, AAvar, - (*thread_private_read_addr_to_call_tree_node_map)[addr], - (*thread_private_write_addr_to_call_tree_node_map)[addr])); + (*thread_private_read_addr_to_call_tree_node_map)[addr], + (*thread_private_write_addr_to_call_tree_node_map)[addr])); dependency_metadata_results_mtx->lock(); dependency_metadata_results->insert(dmd); dependency_metadata_results_mtx->unlock(); @@ -115,15 +117,16 @@ void addDep(depType type, LID curr, LID depOn, const char *var, string AAvar, AD case WAR: // update write // register metadata calculation - // cout << "Register metadata calculation: WAR " << decodeLID(curr) << " " << decodeLID(depOn) << " " << var << " (" + // cout << "Register metadata calculation: WAR " << decodeLID(curr) << " " << decodeLID(depOn) << " " << var << " + // (" // << (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << // (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ") " << " (" << // (*thread_private_write_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << // (*thread_private_write_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ")\n"; dmd = processQueueElement(MetaDataQueueElement(type, curr, depOn, var, AAvar, - (*thread_private_write_addr_to_call_tree_node_map)[addr], - (*thread_private_read_addr_to_call_tree_node_map)[addr])); + (*thread_private_write_addr_to_call_tree_node_map)[addr], + (*thread_private_read_addr_to_call_tree_node_map)[addr])); dependency_metadata_results_mtx->lock(); dependency_metadata_results->insert(dmd); dependency_metadata_results_mtx->unlock(); @@ -131,14 +134,15 @@ void addDep(depType type, LID curr, LID depOn, const char *var, string AAvar, AD break; case WAW: // register metadata calculation - // cout << "Register metadata calculation: WAW " << decodeLID(curr) << " " << decodeLID(depOn) << " " << var << " (" + // cout << "Register metadata calculation: WAW " << decodeLID(curr) << " " << decodeLID(depOn) << " " << var << " + // (" // << (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << // (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ") " << " (" << // (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_loop_or_function_id() << " , " << // (*thread_private_read_addr_to_call_tree_node_map)[addr]->get_iteration_id() << ")\n"; dmd = processQueueElement(MetaDataQueueElement(type, curr, depOn, var, AAvar, - (*thread_private_write_addr_to_call_tree_node_map)[addr], - (*thread_private_write_addr_to_call_tree_node_map)[addr])); + (*thread_private_write_addr_to_call_tree_node_map)[addr], + (*thread_private_write_addr_to_call_tree_node_map)[addr])); dependency_metadata_results_mtx->lock(); dependency_metadata_results->insert(dmd); dependency_metadata_results_mtx->unlock(); @@ -432,7 +436,8 @@ void analyzeSingleAccess(__dp::AbstractShadow *SMem, __dp::AccessInfo &access) { #endif #if DP_CALLTREE_PROFILING addDep(RAW, access.lid, lastWrite, access.var, access.AAvar, access.addr, - thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map, access.calculate_dependency_metadata); + thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map, + access.calculate_dependency_metadata); #else addDep(RAW, access.lid, lastWrite, access.var, access.AAvar, access.addr); #endif @@ -453,7 +458,8 @@ void analyzeSingleAccess(__dp::AbstractShadow *SMem, __dp::AccessInfo &access) { // INIT #if DP_CALLTREE_PROFILING addDep(INIT, access.lid, 0, access.var, access.AAvar, access.addr, - thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map, access.calculate_dependency_metadata); + thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map, + access.calculate_dependency_metadata); #else addDep(INIT, access.lid, 0, access.var, access.AAvar, access.addr); #endif @@ -463,7 +469,8 @@ void analyzeSingleAccess(__dp::AbstractShadow *SMem, __dp::AccessInfo &access) { // WAR #if DP_CALLTREE_PROFILING addDep(WAR, access.lid, lastRead, access.var, access.AAvar, access.addr, - thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map, access.calculate_dependency_metadata); + thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map, + access.calculate_dependency_metadata); #else addDep(WAR, access.lid, lastRead, access.var, access.AAvar, access.addr); #endif @@ -478,7 +485,8 @@ void analyzeSingleAccess(__dp::AbstractShadow *SMem, __dp::AccessInfo &access) { // WAW #if DP_CALLTREE_PROFILING addDep(WAW, access.lid, lastWrite, access.var, access.AAvar, access.addr, - thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map, access.calculate_dependency_metadata); + thread_private_write_addr_to_call_tree_node_map, thread_private_read_addr_to_call_tree_node_map, + access.calculate_dependency_metadata); #else addDep(WAW, access.lid, lastWrite, access.var, access.AAvar, access.addr); #endif diff --git a/test/end_to_end/do_all/backwards_array_access/src/FileMapping.txt b/test/end_to_end/do_all/backwards_array_access/src/FileMapping.txt deleted file mode 100644 index 0e8d2b720..000000000 --- a/test/end_to_end/do_all/backwards_array_access/src/FileMapping.txt +++ /dev/null @@ -1 +0,0 @@ -1 /home/lukas/git/discopop/test/end_to_end/do_all/backwards_array_access/src/code.cpp diff --git a/test/end_to_end/do_all/calls/above_nesting_level_3/src/FileMapping.txt b/test/end_to_end/do_all/calls/above_nesting_level_3/src/FileMapping.txt deleted file mode 100644 index ad7424431..000000000 --- a/test/end_to_end/do_all/calls/above_nesting_level_3/src/FileMapping.txt +++ /dev/null @@ -1 +0,0 @@ -1 /home/lukas/git/discopop/test/end_to_end/do_all/calls/above_nesting_level_3/src/code.cpp diff --git a/test/end_to_end/do_all/calls/above_nesting_level_3/src/code.ll b/test/end_to_end/do_all/calls/above_nesting_level_3/src/code.ll deleted file mode 100644 index cc7c16cfa..000000000 --- a/test/end_to_end/do_all/calls/above_nesting_level_3/src/code.ll +++ /dev/null @@ -1,855 +0,0 @@ -; ModuleID = 'code.cpp' -source_filename = "code.cpp" -target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-unknown-linux-gnu" - -@_ZZ4mainE1n = internal global i32 4000, align 4, !dbg !0 -@.str = private unnamed_addr constant [8 x i8] c"1:5;1:6\00", align 1 -@.str.1 = private unnamed_addr constant [8 x i8] c"1:5;1:8\00", align 1 -@.str.2 = private unnamed_addr constant [4 x i8] c"tmp\00", align 1 -@.str.3 = private unnamed_addr constant [2 x i8] c"i\00", align 1 -@.str.4 = private unnamed_addr constant [4 x i8] c"sum\00", align 1 -@.str.5 = private unnamed_addr constant [2 x i8] c"n\00", align 1 -@.str.6 = private unnamed_addr constant [10 x i8] c"1:14;1:15\00", align 1 -@.str.7 = private unnamed_addr constant [10 x i8] c"1:14;1:17\00", align 1 -@.str.8 = private unnamed_addr constant [10 x i8] c"1:19;1:20\00", align 1 -@.str.9 = private unnamed_addr constant [10 x i8] c"1:19;1:33\00", align 1 -@.str.10 = private unnamed_addr constant [10 x i8] c"1:22;1:23\00", align 1 -@.str.11 = private unnamed_addr constant [10 x i8] c"1:22;1:31\00", align 1 -@.str.12 = private unnamed_addr constant [10 x i8] c"1:25;1:26\00", align 1 -@.str.13 = private unnamed_addr constant [10 x i8] c"1:25;1:29\00", align 1 -@.str.14 = private unnamed_addr constant [12 x i8] c"_ZZ4mainE1n\00", align 1 -@.str.15 = private unnamed_addr constant [5 x i8] c".str\00", align 1 -@.str.16 = private unnamed_addr constant [7 x i8] c".str.1\00", align 1 -@.str.17 = private unnamed_addr constant [7 x i8] c".str.2\00", align 1 -@.str.18 = private unnamed_addr constant [7 x i8] c".str.3\00", align 1 -@.str.19 = private unnamed_addr constant [7 x i8] c".str.4\00", align 1 -@.str.20 = private unnamed_addr constant [7 x i8] c".str.5\00", align 1 -@.str.21 = private unnamed_addr constant [7 x i8] c".str.6\00", align 1 -@.str.22 = private unnamed_addr constant [7 x i8] c".str.7\00", align 1 -@.str.23 = private unnamed_addr constant [7 x i8] c".str.8\00", align 1 -@.str.24 = private unnamed_addr constant [7 x i8] c".str.9\00", align 1 -@.str.25 = private unnamed_addr constant [8 x i8] c".str.10\00", align 1 -@.str.26 = private unnamed_addr constant [8 x i8] c".str.11\00", align 1 -@.str.27 = private unnamed_addr constant [8 x i8] c".str.12\00", align 1 -@.str.28 = private unnamed_addr constant [7 x i8] c"retval\00", align 1 -@.str.29 = private unnamed_addr constant [5 x i8] c"argc\00", align 1 -@.str.30 = private unnamed_addr constant [5 x i8] c"argv\00", align 1 -@.str.31 = private unnamed_addr constant [2 x i8] c"x\00", align 1 -@.str.32 = private unnamed_addr constant [2 x i8] c"k\00", align 1 -@.str.33 = private unnamed_addr constant [2 x i8] c"j\00", align 1 - -; Function Attrs: noinline nounwind optnone uwtable -define i32 @_Z14allowing_doallPdi(double* %tmp, i32 %i) #0 !dbg !263 { -entry: - call void @__dp_func_entry(i32 16388, i32 0) - %__dp_bb1 = alloca i32, align 4 - store i32 0, i32* %__dp_bb1, align 4 - %__dp_bb = alloca i32, align 4 - store i32 0, i32* %__dp_bb, align 4 - %tmp.addr = alloca double*, align 8 - %0 = ptrtoint double** %tmp.addr to i64 - %i.addr = alloca i32, align 4 - %1 = ptrtoint i32* %i.addr to i64 - %sum = alloca i32, align 4 - %2 = ptrtoint i32* %sum to i64 - %n = alloca i32, align 4 - %3 = ptrtoint i32* %n to i64 - %4 = ptrtoint double** %tmp.addr to i64 - store double* %tmp, double** %tmp.addr, align 8 - call void @llvm.dbg.declare(metadata double** %tmp.addr, metadata !266, metadata !DIExpression()), !dbg !267 - %5 = ptrtoint i32* %i.addr to i64 - store i32 %i, i32* %i.addr, align 4 - call void @llvm.dbg.declare(metadata i32* %i.addr, metadata !268, metadata !DIExpression()), !dbg !269 - call void @llvm.dbg.declare(metadata i32* %sum, metadata !270, metadata !DIExpression()), !dbg !271 - %6 = ptrtoint i32* %sum to i64 - store i32 0, i32* %sum, align 4, !dbg !271 - call void @llvm.dbg.declare(metadata i32* %n, metadata !272, metadata !DIExpression()), !dbg !274 - %7 = ptrtoint i32* %n to i64 - store i32 0, i32* %n, align 4, !dbg !274 - call void @__dp_report_bb(i32 0) - br label %for.cond, !dbg !275 - -for.cond: ; preds = %for.inc, %entry - call void @__dp_loop_entry(i32 16390, i32 0) - %8 = ptrtoint i32* %n to i64 - %9 = load i32, i32* %n, align 4, !dbg !276 - %10 = ptrtoint i32* %i.addr to i64 - %11 = load i32, i32* %i.addr, align 4, !dbg !278 - %cmp = icmp slt i32 %9, %11, !dbg !279 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0), i1 %cmp, i32 1), !dbg !280 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.1, i32 0, i32 0), i1 %cmp, i32 0), !dbg !280 - call void @__dp_report_bb(i32 2) - %12 = load i32, i32* %__dp_bb, align 4 - call void @__dp_report_bb_pair(i32 %12, i32 5) - br i1 %cmp, label %for.body, label %for.end, !dbg !280 - -for.body: ; preds = %for.cond - call void @__dp_loop_incr(i32 1) - %13 = ptrtoint double** %tmp.addr to i64 - %14 = load double*, double** %tmp.addr, align 8, !dbg !281 - %15 = ptrtoint i32* %i.addr to i64 - %16 = load i32, i32* %i.addr, align 4, !dbg !283 - %idxprom = sext i32 %16 to i64, !dbg !281 - %arrayidx = getelementptr inbounds double, double* %14, i64 %idxprom, !dbg !281 - %17 = ptrtoint double* %arrayidx to i64 - call void @__dp_read(i32 16391, i64 %17, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.2, i32 0, i32 0)) - %18 = load double, double* %arrayidx, align 8, !dbg !281 - %conv = fptosi double %18 to i32, !dbg !281 - %19 = ptrtoint i32* %sum to i64 - store i32 %conv, i32* %sum, align 4, !dbg !284 - call void @__dp_report_bb(i32 4) - %20 = load i32, i32* %__dp_bb1, align 4 - call void @__dp_report_bb_pair(i32 %20, i32 8) - store i32 1, i32* %__dp_bb1, align 4 - br label %for.inc, !dbg !285 - -for.inc: ; preds = %for.body - %21 = ptrtoint i32* %n to i64 - %22 = load i32, i32* %n, align 4, !dbg !286 - %inc = add nsw i32 %22, 1, !dbg !286 - %23 = ptrtoint i32* %n to i64 - store i32 %inc, i32* %n, align 4, !dbg !286 - call void @__dp_report_bb(i32 3) - %24 = load i32, i32* %__dp_bb, align 4 - call void @__dp_report_bb_pair(i32 %24, i32 6) - store i32 1, i32* %__dp_bb, align 4 - br label %for.cond, !dbg !287, !llvm.loop !288 - -for.end: ; preds = %for.cond - call void @__dp_loop_exit(i32 16393, i32 0) - %25 = ptrtoint i32* %sum to i64 - %26 = load i32, i32* %sum, align 4, !dbg !290 - call void @__dp_report_bb(i32 1) - %27 = load i32, i32* %__dp_bb1, align 4 - call void @__dp_report_bb_pair(i32 %27, i32 7) - call void @__dp_func_exit(i32 16393, i32 0), !dbg !291 - ret i32 %26, !dbg !291 -} - -; Function Attrs: nounwind readnone speculatable willreturn -declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 - -; Function Attrs: noinline norecurse nounwind optnone uwtable -define i32 @main(i32 %argc, i8** %argv) #2 !dbg !2 { -entry: - call void @__dp_func_entry(i32 16396, i32 1) - %__dp_bb35 = alloca i32, align 4 - store i32 0, i32* %__dp_bb35, align 4 - %__dp_bb34 = alloca i32, align 4 - store i32 0, i32* %__dp_bb34, align 4 - %__dp_bb33 = alloca i32, align 4 - store i32 0, i32* %__dp_bb33, align 4 - %__dp_bb32 = alloca i32, align 4 - store i32 0, i32* %__dp_bb32, align 4 - %__dp_bb31 = alloca i32, align 4 - store i32 0, i32* %__dp_bb31, align 4 - %__dp_bb30 = alloca i32, align 4 - store i32 0, i32* %__dp_bb30, align 4 - %__dp_bb = alloca i32, align 4 - store i32 0, i32* %__dp_bb, align 4 - %retval = alloca i32, align 4 - %0 = ptrtoint i32* %retval to i64 - %argc.addr = alloca i32, align 4 - %1 = ptrtoint i32* %argc.addr to i64 - %argv.addr = alloca i8**, align 8 - %2 = ptrtoint i8*** %argv.addr to i64 - %x = alloca double*, align 8 - %3 = ptrtoint double** %x to i64 - %i = alloca i32, align 4 - %4 = ptrtoint i32* %i to i64 - %k = alloca i32, align 4 - %5 = ptrtoint i32* %k to i64 - %j = alloca i32, align 4 - %6 = ptrtoint i32* %j to i64 - %i7 = alloca i32, align 4 - %7 = ptrtoint i32* %i7 to i64 - %sum = alloca i32, align 4 - %8 = ptrtoint i32* %sum to i64 - %9 = ptrtoint i32* %retval to i64 - store i32 0, i32* %retval, align 4 - %10 = ptrtoint i32* %argc.addr to i64 - store i32 %argc, i32* %argc.addr, align 4 - call void @llvm.dbg.declare(metadata i32* %argc.addr, metadata !292, metadata !DIExpression()), !dbg !293 - %11 = ptrtoint i8*** %argv.addr to i64 - store i8** %argv, i8*** %argv.addr, align 8 - call void @llvm.dbg.declare(metadata i8*** %argv.addr, metadata !294, metadata !DIExpression()), !dbg !295 - call void @llvm.dbg.declare(metadata double** %x, metadata !296, metadata !DIExpression()), !dbg !297 - %12 = ptrtoint i32* @_ZZ4mainE1n to i64 - call void @__dp_read(i32 16398, i64 %12, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.14, i32 0, i32 0)) - %13 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !298 - %conv = sext i32 %13 to i64, !dbg !298 - %mul = mul i64 %conv, 8, !dbg !299 - %call = call noalias i8* @malloc(i64 %mul) #4, !dbg !300 - %14 = ptrtoint i8* %call to i64 - call void @__dp_new(i32 16398, i64 %14, i64 %14, i64 %mul), !dbg !301 - %15 = bitcast i8* %call to double*, !dbg !301 - %16 = ptrtoint double** %x to i64 - store double* %15, double** %x, align 8, !dbg !297 - call void @llvm.dbg.declare(metadata i32* %i, metadata !302, metadata !DIExpression()), !dbg !304 - %17 = ptrtoint i32* %i to i64 - store i32 0, i32* %i, align 4, !dbg !304 - call void @__dp_report_bb(i32 9) - br label %for.cond, !dbg !305 - -for.cond: ; preds = %for.inc, %entry - call void @__dp_loop_entry(i32 16401, i32 1) - %18 = ptrtoint i32* %i to i64 - %19 = load i32, i32* %i, align 4, !dbg !306 - %20 = ptrtoint i32* @_ZZ4mainE1n to i64 - call void @__dp_read(i32 16401, i64 %20, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.14, i32 0, i32 0)) - %21 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !308 - %cmp = icmp slt i32 %19, %21, !dbg !309 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.6, i32 0, i32 0), i1 %cmp, i32 1), !dbg !310 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.7, i32 0, i32 0), i1 %cmp, i32 0), !dbg !310 - call void @__dp_report_bb(i32 11) - %22 = load i32, i32* %__dp_bb, align 4 - call void @__dp_report_bb_pair(i32 %22, i32 24) - br i1 %cmp, label %for.body, label %for.end, !dbg !310 - -for.body: ; preds = %for.cond - call void @__dp_loop_incr(i32 5) - %23 = ptrtoint double** %x to i64 - %24 = load double*, double** %x, align 8, !dbg !311 - %25 = ptrtoint i32* %i to i64 - %26 = load i32, i32* %i, align 4, !dbg !313 - %idxprom = sext i32 %26 to i64, !dbg !311 - %arrayidx = getelementptr inbounds double, double* %24, i64 %idxprom, !dbg !311 - %27 = ptrtoint double* %arrayidx to i64 - call void @__dp_write(i32 16402, i64 %27, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.31, i32 0, i32 0)) - store double 1.000000e+00, double* %arrayidx, align 8, !dbg !314 - call void @__dp_report_bb(i32 13) - %28 = load i32, i32* %__dp_bb, align 4 - call void @__dp_report_bb_pair(i32 %28, i32 26) - br label %for.inc, !dbg !315 - -for.inc: ; preds = %for.body - %29 = ptrtoint i32* %i to i64 - %30 = load i32, i32* %i, align 4, !dbg !316 - %inc = add nsw i32 %30, 1, !dbg !316 - %31 = ptrtoint i32* %i to i64 - store i32 %inc, i32* %i, align 4, !dbg !316 - call void @__dp_report_bb(i32 12) - %32 = load i32, i32* %__dp_bb, align 4 - call void @__dp_report_bb_pair(i32 %32, i32 25) - store i32 1, i32* %__dp_bb, align 4 - br label %for.cond, !dbg !317, !llvm.loop !318 - -for.end: ; preds = %for.cond - call void @__dp_loop_exit(i32 16404, i32 1) - call void @llvm.dbg.declare(metadata i32* %k, metadata !320, metadata !DIExpression()), !dbg !322 - %33 = ptrtoint i32* %k to i64 - store i32 0, i32* %k, align 4, !dbg !322 - call void @__dp_report_bb(i32 10) - br label %for.cond1, !dbg !323 - -for.cond1: ; preds = %for.inc27, %for.end - call void @__dp_loop_entry(i32 16404, i32 2) - %34 = ptrtoint i32* %k to i64 - %35 = load i32, i32* %k, align 4, !dbg !324 - %cmp2 = icmp slt i32 %35, 20, !dbg !326 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.8, i32 0, i32 0), i1 %cmp2, i32 1), !dbg !327 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.9, i32 0, i32 0), i1 %cmp2, i32 0), !dbg !327 - call void @__dp_report_bb(i32 15) - %36 = load i32, i32* %__dp_bb30, align 4 - call void @__dp_report_bb_pair(i32 %36, i32 27) - br i1 %cmp2, label %for.body3, label %for.end29, !dbg !327 - -for.body3: ; preds = %for.cond1 - call void @__dp_loop_incr(i32 2) - call void @llvm.dbg.declare(metadata i32* %j, metadata !328, metadata !DIExpression()), !dbg !331 - %37 = ptrtoint i32* %j to i64 - store i32 0, i32* %j, align 4, !dbg !331 - call void @__dp_report_bb(i32 17) - %38 = load i32, i32* %__dp_bb32, align 4 - call void @__dp_report_bb_pair(i32 %38, i32 31) - br label %for.cond4, !dbg !332 - -for.cond4: ; preds = %for.inc24, %for.body3 - call void @__dp_loop_entry(i32 16405, i32 3) - %39 = ptrtoint i32* %j to i64 - %40 = load i32, i32* %j, align 4, !dbg !333 - %cmp5 = icmp slt i32 %40, 20, !dbg !335 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.10, i32 0, i32 0), i1 %cmp5, i32 1), !dbg !336 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.11, i32 0, i32 0), i1 %cmp5, i32 0), !dbg !336 - call void @__dp_report_bb(i32 19) - store i32 1, i32* %__dp_bb32, align 4 - %41 = load i32, i32* %__dp_bb33, align 4 - call void @__dp_report_bb_pair(i32 %41, i32 33) - br i1 %cmp5, label %for.body6, label %for.end26, !dbg !336 - -for.body6: ; preds = %for.cond4 - call void @__dp_loop_incr(i32 3) - call void @llvm.dbg.declare(metadata i32* %i7, metadata !337, metadata !DIExpression()), !dbg !340 - %42 = ptrtoint i32* %i7 to i64 - store i32 0, i32* %i7, align 4, !dbg !340 - call void @__dp_report_bb(i32 21) - %43 = load i32, i32* %__dp_bb34, align 4 - call void @__dp_report_bb_pair(i32 %43, i32 35) - br label %for.cond8, !dbg !341 - -for.cond8: ; preds = %for.inc21, %for.body6 - call void @__dp_loop_entry(i32 16406, i32 4) - %44 = ptrtoint i32* %i7 to i64 - %45 = load i32, i32* %i7, align 4, !dbg !342 - %46 = ptrtoint i32* @_ZZ4mainE1n to i64 - call void @__dp_read(i32 16406, i64 %46, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.14, i32 0, i32 0)) - %47 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !344 - %div = sdiv i32 %47, 400, !dbg !345 - %cmp9 = icmp slt i32 %45, %div, !dbg !346 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.12, i32 0, i32 0), i1 %cmp9, i32 1), !dbg !347 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.13, i32 0, i32 0), i1 %cmp9, i32 0), !dbg !347 - call void @__dp_report_bb(i32 22) - store i32 1, i32* %__dp_bb34, align 4 - %48 = load i32, i32* %__dp_bb35, align 4 - call void @__dp_report_bb_pair(i32 %48, i32 37) - br i1 %cmp9, label %for.body10, label %for.end23, !dbg !347 - -for.body10: ; preds = %for.cond8 - call void @__dp_loop_incr(i32 4) - call void @llvm.dbg.declare(metadata i32* %sum, metadata !348, metadata !DIExpression()), !dbg !350 - %49 = ptrtoint double** %x to i64 - %50 = load double*, double** %x, align 8, !dbg !351 - %51 = ptrtoint i32* %k to i64 - %52 = load i32, i32* %k, align 4, !dbg !352 - %53 = ptrtoint i32* @_ZZ4mainE1n to i64 - call void @__dp_read(i32 16407, i64 %53, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.14, i32 0, i32 0)) - %54 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !353 - %div11 = sdiv i32 %54, 20, !dbg !354 - %mul12 = mul nsw i32 %52, %div11, !dbg !355 - %idx.ext = sext i32 %mul12 to i64, !dbg !356 - %add.ptr = getelementptr inbounds double, double* %50, i64 %idx.ext, !dbg !356 - %55 = ptrtoint i32* %j to i64 - %56 = load i32, i32* %j, align 4, !dbg !357 - %57 = ptrtoint i32* @_ZZ4mainE1n to i64 - call void @__dp_read(i32 16407, i64 %57, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.14, i32 0, i32 0)) - %58 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !358 - %div13 = sdiv i32 %58, 400, !dbg !359 - %mul14 = mul nsw i32 %56, %div13, !dbg !360 - %idx.ext15 = sext i32 %mul14 to i64, !dbg !361 - %add.ptr16 = getelementptr inbounds double, double* %add.ptr, i64 %idx.ext15, !dbg !361 - %59 = ptrtoint i32* %i7 to i64 - %60 = load i32, i32* %i7, align 4, !dbg !362 - %idx.ext17 = sext i32 %60 to i64, !dbg !363 - %add.ptr18 = getelementptr inbounds double, double* %add.ptr16, i64 %idx.ext17, !dbg !363 - %61 = ptrtoint i32* @_ZZ4mainE1n to i64 - call void @__dp_read(i32 16407, i64 %61, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.14, i32 0, i32 0)) - %62 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !364 - %div19 = sdiv i32 %62, 400, !dbg !365 - %63 = ptrtoint i32* %i7 to i64 - %64 = load i32, i32* %i7, align 4, !dbg !366 - %sub = sub nsw i32 %div19, %64, !dbg !367 - call void @__dp_call(i32 16407), !dbg !368 - %call20 = call i32 @_Z14allowing_doallPdi(double* %add.ptr18, i32 %sub), !dbg !368 - %65 = ptrtoint i32* %sum to i64 - store i32 %call20, i32* %sum, align 4, !dbg !350 - call void @__dp_report_bb(i32 18) - %66 = load i32, i32* %__dp_bb30, align 4 - call void @__dp_report_bb_pair(i32 %66, i32 29) - %67 = load i32, i32* %__dp_bb31, align 4 - call void @__dp_report_bb_pair(i32 %67, i32 30) - store i32 1, i32* %__dp_bb31, align 4 - %68 = load i32, i32* %__dp_bb33, align 4 - call void @__dp_report_bb_pair(i32 %68, i32 32) - %69 = load i32, i32* %__dp_bb35, align 4 - call void @__dp_report_bb_pair(i32 %69, i32 36) - br label %for.inc21, !dbg !369 - -for.inc21: ; preds = %for.body10 - %70 = ptrtoint i32* %i7 to i64 - %71 = load i32, i32* %i7, align 4, !dbg !370 - %inc22 = add nsw i32 %71, 1, !dbg !370 - %72 = ptrtoint i32* %i7 to i64 - store i32 %inc22, i32* %i7, align 4, !dbg !370 - call void @__dp_report_bb(i32 23) - %73 = load i32, i32* %__dp_bb35, align 4 - call void @__dp_report_bb_pair(i32 %73, i32 38) - store i32 1, i32* %__dp_bb35, align 4 - br label %for.cond8, !dbg !371, !llvm.loop !372 - -for.end23: ; preds = %for.cond8 - call void @__dp_loop_exit(i32 16409, i32 4) - br label %for.inc24, !dbg !374 - -for.inc24: ; preds = %for.end23 - %74 = ptrtoint i32* %j to i64 - %75 = load i32, i32* %j, align 4, !dbg !375 - %inc25 = add nsw i32 %75, 1, !dbg !375 - %76 = ptrtoint i32* %j to i64 - store i32 %inc25, i32* %j, align 4, !dbg !375 - call void @__dp_report_bb(i32 20) - %77 = load i32, i32* %__dp_bb33, align 4 - call void @__dp_report_bb_pair(i32 %77, i32 34) - store i32 1, i32* %__dp_bb33, align 4 - br label %for.cond4, !dbg !376, !llvm.loop !377 - -for.end26: ; preds = %for.cond4 - call void @__dp_loop_exit(i32 16410, i32 3) - br label %for.inc27, !dbg !379 - -for.inc27: ; preds = %for.end26 - %78 = ptrtoint i32* %k to i64 - %79 = load i32, i32* %k, align 4, !dbg !380 - %inc28 = add nsw i32 %79, 1, !dbg !380 - %80 = ptrtoint i32* %k to i64 - store i32 %inc28, i32* %k, align 4, !dbg !380 - call void @__dp_report_bb(i32 16) - %81 = load i32, i32* %__dp_bb30, align 4 - call void @__dp_report_bb_pair(i32 %81, i32 28) - store i32 1, i32* %__dp_bb30, align 4 - br label %for.cond1, !dbg !381, !llvm.loop !382 - -for.end29: ; preds = %for.cond1 - call void @__dp_loop_exit(i32 16412, i32 2) - %82 = ptrtoint double** %x to i64 - %83 = load double*, double** %x, align 8, !dbg !384 - %84 = bitcast double* %83 to i8*, !dbg !384 - call void @free(i8* %84) #4, !dbg !385 - %85 = ptrtoint i8* %84 to i64 - call void @__dp_delete(i32 16412, i64 %85), !dbg !386 - call void @__dp_report_bb(i32 14) - call void @__dp_finalize(i32 16413), !dbg !386 - call void @__dp_loop_output(), !dbg !386 - call void @__dp_taken_branch_counter_output(), !dbg !386 - ret i32 0, !dbg !386 -} - -; Function Attrs: nounwind -declare noalias i8* @malloc(i64) #3 - -; Function Attrs: nounwind -declare void @free(i8*) #3 - -declare void @__dp_init(i32, i32, i32) - -declare void @__dp_finalize(i32) - -declare void @__dp_read(i32, i64, i8*) - -declare void @__dp_write(i32, i64, i8*) - -declare void @__dp_alloca(i32, i8*, i64, i64, i64, i64) - -declare void @__dp_new(i32, i64, i64, i64) - -declare void @__dp_delete(i32, i64) - -declare void @__dp_call(i32) - -declare void @__dp_func_entry(i32, i32) - -declare void @__dp_func_exit(i32, i32) - -declare void @__dp_loop_entry(i32, i32) - -declare void @__dp_loop_exit(i32, i32) - -declare void @__dp_incr_taken_branch_counter(i8*, i32, i32) - -declare void @__dp_report_bb(i32) - -declare void @__dp_report_bb_pair(i32, i32) - -declare void @__dp_loop_incr(i32) - -declare void @__dp_loop_output() - -declare void @__dp_taken_branch_counter_output() - -attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { nounwind readnone speculatable willreturn } -attributes #2 = { noinline norecurse nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #3 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #4 = { nounwind } - -!llvm.dbg.cu = !{!11} -!llvm.module.flags = !{!258, !259, !260, !261} -!llvm.ident = !{!262} - -!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) -!1 = distinct !DIGlobalVariable(name: "n", scope: !2, file: !3, line: 13, type: !6, isLocal: true, isDefinition: true) -!2 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 12, type: !4, scopeLine: 12, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !11, retainedNodes: !12) -!3 = !DIFile(filename: "code.cpp", directory: "/home/lukas/git/discopop/test/end_to_end/do_all/calls/above_nesting_level_3/src") -!4 = !DISubroutineType(types: !5) -!5 = !{!6, !6, !7} -!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) -!7 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64) -!8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64) -!9 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !10) -!10 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) -!11 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 11.1.0 (https://github.com/llvm/llvm-project.git 7e99bddfeaab2713a8bb6ca538da25b66e6efc59)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !12, retainedTypes: !13, globals: !16, imports: !17, splitDebugInlining: false, nameTableKind: None) -!12 = !{} -!13 = !{!14} -!14 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !15, size: 64) -!15 = !DIBasicType(name: "double", size: 64, encoding: DW_ATE_float) -!16 = !{!0} -!17 = !{!18, !25, !29, !36, !40, !45, !47, !51, !55, !59, !73, !77, !81, !85, !89, !94, !98, !102, !106, !110, !118, !122, !126, !128, !132, !136, !141, !147, !151, !155, !157, !165, !169, !177, !179, !183, !187, !191, !195, !200, !205, !210, !211, !212, !213, !215, !216, !217, !218, !219, !220, !221, !223, !224, !225, !226, !227, !228, !229, !234, !235, !236, !237, !238, !239, !240, !241, !242, !243, !244, !245, !246, !247, !248, !249, !250, !251, !252, !253, !254, !255, !256, !257} -!18 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !20, file: !24, line: 52) -!19 = !DINamespace(name: "std", scope: null) -!20 = !DISubprogram(name: "abs", scope: !21, file: !21, line: 848, type: !22, flags: DIFlagPrototyped, spFlags: 0) -!21 = !DIFile(filename: "/usr/include/stdlib.h", directory: "") -!22 = !DISubroutineType(types: !23) -!23 = !{!6, !6} -!24 = !DIFile(filename: "/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/bits/std_abs.h", directory: "") -!25 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !26, file: !28, line: 127) -!26 = !DIDerivedType(tag: DW_TAG_typedef, name: "div_t", file: !21, line: 63, baseType: !27) -!27 = !DICompositeType(tag: DW_TAG_structure_type, file: !21, line: 59, flags: DIFlagFwdDecl, identifier: "_ZTS5div_t") -!28 = !DIFile(filename: "/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/cstdlib", directory: "") -!29 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !30, file: !28, line: 128) -!30 = !DIDerivedType(tag: DW_TAG_typedef, name: "ldiv_t", file: !21, line: 71, baseType: !31) -!31 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !21, line: 67, size: 128, flags: DIFlagTypePassByValue, elements: !32, identifier: "_ZTS6ldiv_t") -!32 = !{!33, !35} -!33 = !DIDerivedType(tag: DW_TAG_member, name: "quot", scope: !31, file: !21, line: 69, baseType: !34, size: 64) -!34 = !DIBasicType(name: "long int", size: 64, encoding: DW_ATE_signed) -!35 = !DIDerivedType(tag: DW_TAG_member, name: "rem", scope: !31, file: !21, line: 70, baseType: !34, size: 64, offset: 64) -!36 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !37, file: !28, line: 130) -!37 = !DISubprogram(name: "abort", scope: !21, file: !21, line: 598, type: !38, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) -!38 = !DISubroutineType(types: !39) -!39 = !{null} -!40 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !41, file: !28, line: 134) -!41 = !DISubprogram(name: "atexit", scope: !21, file: !21, line: 602, type: !42, flags: DIFlagPrototyped, spFlags: 0) -!42 = !DISubroutineType(types: !43) -!43 = !{!6, !44} -!44 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !38, size: 64) -!45 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !46, file: !28, line: 137) -!46 = !DISubprogram(name: "at_quick_exit", scope: !21, file: !21, line: 607, type: !42, flags: DIFlagPrototyped, spFlags: 0) -!47 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !48, file: !28, line: 140) -!48 = !DISubprogram(name: "atof", scope: !21, file: !21, line: 102, type: !49, flags: DIFlagPrototyped, spFlags: 0) -!49 = !DISubroutineType(types: !50) -!50 = !{!15, !8} -!51 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !52, file: !28, line: 141) -!52 = !DISubprogram(name: "atoi", scope: !21, file: !21, line: 105, type: !53, flags: DIFlagPrototyped, spFlags: 0) -!53 = !DISubroutineType(types: !54) -!54 = !{!6, !8} -!55 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !56, file: !28, line: 142) -!56 = !DISubprogram(name: "atol", scope: !21, file: !21, line: 108, type: !57, flags: DIFlagPrototyped, spFlags: 0) -!57 = !DISubroutineType(types: !58) -!58 = !{!34, !8} -!59 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !60, file: !28, line: 143) -!60 = !DISubprogram(name: "bsearch", scope: !21, file: !21, line: 828, type: !61, flags: DIFlagPrototyped, spFlags: 0) -!61 = !DISubroutineType(types: !62) -!62 = !{!63, !64, !64, !66, !66, !69} -!63 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) -!64 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !65, size: 64) -!65 = !DIDerivedType(tag: DW_TAG_const_type, baseType: null) -!66 = !DIDerivedType(tag: DW_TAG_typedef, name: "size_t", file: !67, line: 46, baseType: !68) -!67 = !DIFile(filename: "Software/llvm-11.1.0/lib/clang/11.1.0/include/stddef.h", directory: "/home/lukas") -!68 = !DIBasicType(name: "long unsigned int", size: 64, encoding: DW_ATE_unsigned) -!69 = !DIDerivedType(tag: DW_TAG_typedef, name: "__compar_fn_t", file: !21, line: 816, baseType: !70) -!70 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !71, size: 64) -!71 = !DISubroutineType(types: !72) -!72 = !{!6, !64, !64} -!73 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !74, file: !28, line: 144) -!74 = !DISubprogram(name: "calloc", scope: !21, file: !21, line: 543, type: !75, flags: DIFlagPrototyped, spFlags: 0) -!75 = !DISubroutineType(types: !76) -!76 = !{!63, !66, !66} -!77 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !78, file: !28, line: 145) -!78 = !DISubprogram(name: "div", scope: !21, file: !21, line: 860, type: !79, flags: DIFlagPrototyped, spFlags: 0) -!79 = !DISubroutineType(types: !80) -!80 = !{!26, !6, !6} -!81 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !82, file: !28, line: 146) -!82 = !DISubprogram(name: "exit", scope: !21, file: !21, line: 624, type: !83, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) -!83 = !DISubroutineType(types: !84) -!84 = !{null, !6} -!85 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !86, file: !28, line: 147) -!86 = !DISubprogram(name: "free", scope: !21, file: !21, line: 555, type: !87, flags: DIFlagPrototyped, spFlags: 0) -!87 = !DISubroutineType(types: !88) -!88 = !{null, !63} -!89 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !90, file: !28, line: 148) -!90 = !DISubprogram(name: "getenv", scope: !21, file: !21, line: 641, type: !91, flags: DIFlagPrototyped, spFlags: 0) -!91 = !DISubroutineType(types: !92) -!92 = !{!93, !8} -!93 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64) -!94 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !95, file: !28, line: 149) -!95 = !DISubprogram(name: "labs", scope: !21, file: !21, line: 849, type: !96, flags: DIFlagPrototyped, spFlags: 0) -!96 = !DISubroutineType(types: !97) -!97 = !{!34, !34} -!98 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !99, file: !28, line: 150) -!99 = !DISubprogram(name: "ldiv", scope: !21, file: !21, line: 862, type: !100, flags: DIFlagPrototyped, spFlags: 0) -!100 = !DISubroutineType(types: !101) -!101 = !{!30, !34, !34} -!102 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !103, file: !28, line: 151) -!103 = !DISubprogram(name: "malloc", scope: !21, file: !21, line: 540, type: !104, flags: DIFlagPrototyped, spFlags: 0) -!104 = !DISubroutineType(types: !105) -!105 = !{!63, !66} -!106 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !107, file: !28, line: 153) -!107 = !DISubprogram(name: "mblen", scope: !21, file: !21, line: 930, type: !108, flags: DIFlagPrototyped, spFlags: 0) -!108 = !DISubroutineType(types: !109) -!109 = !{!6, !8, !66} -!110 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !111, file: !28, line: 154) -!111 = !DISubprogram(name: "mbstowcs", scope: !21, file: !21, line: 941, type: !112, flags: DIFlagPrototyped, spFlags: 0) -!112 = !DISubroutineType(types: !113) -!113 = !{!66, !114, !117, !66} -!114 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !115) -!115 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !116, size: 64) -!116 = !DIBasicType(name: "wchar_t", size: 32, encoding: DW_ATE_signed) -!117 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !8) -!118 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !119, file: !28, line: 155) -!119 = !DISubprogram(name: "mbtowc", scope: !21, file: !21, line: 933, type: !120, flags: DIFlagPrototyped, spFlags: 0) -!120 = !DISubroutineType(types: !121) -!121 = !{!6, !114, !117, !66} -!122 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !123, file: !28, line: 157) -!123 = !DISubprogram(name: "qsort", scope: !21, file: !21, line: 838, type: !124, flags: DIFlagPrototyped, spFlags: 0) -!124 = !DISubroutineType(types: !125) -!125 = !{null, !63, !66, !66, !69} -!126 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !127, file: !28, line: 160) -!127 = !DISubprogram(name: "quick_exit", scope: !21, file: !21, line: 630, type: !83, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) -!128 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !129, file: !28, line: 163) -!129 = !DISubprogram(name: "rand", scope: !21, file: !21, line: 454, type: !130, flags: DIFlagPrototyped, spFlags: 0) -!130 = !DISubroutineType(types: !131) -!131 = !{!6} -!132 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !133, file: !28, line: 164) -!133 = !DISubprogram(name: "realloc", scope: !21, file: !21, line: 551, type: !134, flags: DIFlagPrototyped, spFlags: 0) -!134 = !DISubroutineType(types: !135) -!135 = !{!63, !63, !66} -!136 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !137, file: !28, line: 165) -!137 = !DISubprogram(name: "srand", scope: !21, file: !21, line: 456, type: !138, flags: DIFlagPrototyped, spFlags: 0) -!138 = !DISubroutineType(types: !139) -!139 = !{null, !140} -!140 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned) -!141 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !142, file: !28, line: 166) -!142 = !DISubprogram(name: "strtod", scope: !21, file: !21, line: 118, type: !143, flags: DIFlagPrototyped, spFlags: 0) -!143 = !DISubroutineType(types: !144) -!144 = !{!15, !117, !145} -!145 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !146) -!146 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !93, size: 64) -!147 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !148, file: !28, line: 167) -!148 = !DISubprogram(name: "strtol", scope: !21, file: !21, line: 177, type: !149, flags: DIFlagPrototyped, spFlags: 0) -!149 = !DISubroutineType(types: !150) -!150 = !{!34, !117, !145, !6} -!151 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !152, file: !28, line: 168) -!152 = !DISubprogram(name: "strtoul", scope: !21, file: !21, line: 181, type: !153, flags: DIFlagPrototyped, spFlags: 0) -!153 = !DISubroutineType(types: !154) -!154 = !{!68, !117, !145, !6} -!155 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !156, file: !28, line: 169) -!156 = !DISubprogram(name: "system", scope: !21, file: !21, line: 791, type: !53, flags: DIFlagPrototyped, spFlags: 0) -!157 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !158, file: !28, line: 171) -!158 = !DISubprogram(name: "wcstombs", scope: !21, file: !21, line: 945, type: !159, flags: DIFlagPrototyped, spFlags: 0) -!159 = !DISubroutineType(types: !160) -!160 = !{!66, !161, !162, !66} -!161 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !93) -!162 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !163) -!163 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !164, size: 64) -!164 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !116) -!165 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !166, file: !28, line: 172) -!166 = !DISubprogram(name: "wctomb", scope: !21, file: !21, line: 937, type: !167, flags: DIFlagPrototyped, spFlags: 0) -!167 = !DISubroutineType(types: !168) -!168 = !{!6, !93, !116} -!169 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !171, file: !28, line: 200) -!170 = !DINamespace(name: "__gnu_cxx", scope: null) -!171 = !DIDerivedType(tag: DW_TAG_typedef, name: "lldiv_t", file: !21, line: 81, baseType: !172) -!172 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !21, line: 77, size: 128, flags: DIFlagTypePassByValue, elements: !173, identifier: "_ZTS7lldiv_t") -!173 = !{!174, !176} -!174 = !DIDerivedType(tag: DW_TAG_member, name: "quot", scope: !172, file: !21, line: 79, baseType: !175, size: 64) -!175 = !DIBasicType(name: "long long int", size: 64, encoding: DW_ATE_signed) -!176 = !DIDerivedType(tag: DW_TAG_member, name: "rem", scope: !172, file: !21, line: 80, baseType: !175, size: 64, offset: 64) -!177 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !178, file: !28, line: 206) -!178 = !DISubprogram(name: "_Exit", scope: !21, file: !21, line: 636, type: !83, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) -!179 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !180, file: !28, line: 210) -!180 = !DISubprogram(name: "llabs", scope: !21, file: !21, line: 852, type: !181, flags: DIFlagPrototyped, spFlags: 0) -!181 = !DISubroutineType(types: !182) -!182 = !{!175, !175} -!183 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !184, file: !28, line: 216) -!184 = !DISubprogram(name: "lldiv", scope: !21, file: !21, line: 866, type: !185, flags: DIFlagPrototyped, spFlags: 0) -!185 = !DISubroutineType(types: !186) -!186 = !{!171, !175, !175} -!187 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !188, file: !28, line: 227) -!188 = !DISubprogram(name: "atoll", scope: !21, file: !21, line: 113, type: !189, flags: DIFlagPrototyped, spFlags: 0) -!189 = !DISubroutineType(types: !190) -!190 = !{!175, !8} -!191 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !192, file: !28, line: 228) -!192 = !DISubprogram(name: "strtoll", scope: !21, file: !21, line: 201, type: !193, flags: DIFlagPrototyped, spFlags: 0) -!193 = !DISubroutineType(types: !194) -!194 = !{!175, !117, !145, !6} -!195 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !196, file: !28, line: 229) -!196 = !DISubprogram(name: "strtoull", scope: !21, file: !21, line: 206, type: !197, flags: DIFlagPrototyped, spFlags: 0) -!197 = !DISubroutineType(types: !198) -!198 = !{!199, !117, !145, !6} -!199 = !DIBasicType(name: "long long unsigned int", size: 64, encoding: DW_ATE_unsigned) -!200 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !201, file: !28, line: 231) -!201 = !DISubprogram(name: "strtof", scope: !21, file: !21, line: 124, type: !202, flags: DIFlagPrototyped, spFlags: 0) -!202 = !DISubroutineType(types: !203) -!203 = !{!204, !117, !145} -!204 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) -!205 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !206, file: !28, line: 232) -!206 = !DISubprogram(name: "strtold", scope: !21, file: !21, line: 127, type: !207, flags: DIFlagPrototyped, spFlags: 0) -!207 = !DISubroutineType(types: !208) -!208 = !{!209, !117, !145} -!209 = !DIBasicType(name: "long double", size: 128, encoding: DW_ATE_float) -!210 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !171, file: !28, line: 240) -!211 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !178, file: !28, line: 242) -!212 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !180, file: !28, line: 244) -!213 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !214, file: !28, line: 245) -!214 = !DISubprogram(name: "div", linkageName: "_ZN9__gnu_cxx3divExx", scope: !170, file: !28, line: 213, type: !185, flags: DIFlagPrototyped, spFlags: 0) -!215 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !184, file: !28, line: 246) -!216 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !188, file: !28, line: 248) -!217 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !201, file: !28, line: 249) -!218 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !192, file: !28, line: 250) -!219 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !196, file: !28, line: 251) -!220 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !206, file: !28, line: 252) -!221 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !37, file: !222, line: 38) -!222 = !DIFile(filename: "/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/stdlib.h", directory: "") -!223 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !41, file: !222, line: 39) -!224 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !82, file: !222, line: 40) -!225 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !46, file: !222, line: 43) -!226 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !127, file: !222, line: 46) -!227 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !26, file: !222, line: 51) -!228 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !30, file: !222, line: 52) -!229 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !230, file: !222, line: 54) -!230 = !DISubprogram(name: "abs", linkageName: "_ZSt3absg", scope: !19, file: !24, line: 103, type: !231, flags: DIFlagPrototyped, spFlags: 0) -!231 = !DISubroutineType(types: !232) -!232 = !{!233, !233} -!233 = !DIBasicType(name: "__float128", size: 128, encoding: DW_ATE_float) -!234 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !48, file: !222, line: 55) -!235 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !52, file: !222, line: 56) -!236 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !56, file: !222, line: 57) -!237 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !60, file: !222, line: 58) -!238 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !74, file: !222, line: 59) -!239 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !214, file: !222, line: 60) -!240 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !86, file: !222, line: 61) -!241 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !90, file: !222, line: 62) -!242 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !95, file: !222, line: 63) -!243 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !99, file: !222, line: 64) -!244 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !103, file: !222, line: 65) -!245 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !107, file: !222, line: 67) -!246 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !111, file: !222, line: 68) -!247 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !119, file: !222, line: 69) -!248 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !123, file: !222, line: 71) -!249 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !129, file: !222, line: 72) -!250 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !133, file: !222, line: 73) -!251 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !137, file: !222, line: 74) -!252 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !142, file: !222, line: 75) -!253 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !148, file: !222, line: 76) -!254 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !152, file: !222, line: 77) -!255 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !156, file: !222, line: 78) -!256 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !158, file: !222, line: 80) -!257 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !166, file: !222, line: 81) -!258 = !{i32 7, !"Dwarf Version", i32 4} -!259 = !{i32 2, !"Debug Info Version", i32 3} -!260 = !{i32 1, !"wchar_size", i32 4} -!261 = !{i32 7, !"PIC Level", i32 2} -!262 = !{!"clang version 11.1.0 (https://github.com/llvm/llvm-project.git 7e99bddfeaab2713a8bb6ca538da25b66e6efc59)"} -!263 = distinct !DISubprogram(name: "allowing_doall", linkageName: "_Z14allowing_doallPdi", scope: !3, file: !3, line: 4, type: !264, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !11, retainedNodes: !12) -!264 = !DISubroutineType(types: !265) -!265 = !{!6, !14, !6} -!266 = !DILocalVariable(name: "tmp", arg: 1, scope: !263, file: !3, line: 4, type: !14) -!267 = !DILocation(line: 4, column: 27, scope: !263) -!268 = !DILocalVariable(name: "i", arg: 2, scope: !263, file: !3, line: 4, type: !6) -!269 = !DILocation(line: 4, column: 38, scope: !263) -!270 = !DILocalVariable(name: "sum", scope: !263, file: !3, line: 5, type: !6) -!271 = !DILocation(line: 5, column: 7, scope: !263) -!272 = !DILocalVariable(name: "n", scope: !273, file: !3, line: 6, type: !6) -!273 = distinct !DILexicalBlock(scope: !263, file: !3, line: 6, column: 3) -!274 = !DILocation(line: 6, column: 12, scope: !273) -!275 = !DILocation(line: 6, column: 8, scope: !273) -!276 = !DILocation(line: 6, column: 19, scope: !277) -!277 = distinct !DILexicalBlock(scope: !273, file: !3, line: 6, column: 3) -!278 = !DILocation(line: 6, column: 23, scope: !277) -!279 = !DILocation(line: 6, column: 21, scope: !277) -!280 = !DILocation(line: 6, column: 3, scope: !273) -!281 = !DILocation(line: 7, column: 11, scope: !282) -!282 = distinct !DILexicalBlock(scope: !277, file: !3, line: 6, column: 31) -!283 = !DILocation(line: 7, column: 15, scope: !282) -!284 = !DILocation(line: 7, column: 9, scope: !282) -!285 = !DILocation(line: 8, column: 3, scope: !282) -!286 = !DILocation(line: 6, column: 27, scope: !277) -!287 = !DILocation(line: 6, column: 3, scope: !277) -!288 = distinct !{!288, !280, !289} -!289 = !DILocation(line: 8, column: 3, scope: !273) -!290 = !DILocation(line: 9, column: 10, scope: !263) -!291 = !DILocation(line: 9, column: 3, scope: !263) -!292 = !DILocalVariable(name: "argc", arg: 1, scope: !2, file: !3, line: 12, type: !6) -!293 = !DILocation(line: 12, column: 14, scope: !2) -!294 = !DILocalVariable(name: "argv", arg: 2, scope: !2, file: !3, line: 12, type: !7) -!295 = !DILocation(line: 12, column: 32, scope: !2) -!296 = !DILocalVariable(name: "x", scope: !2, file: !3, line: 14, type: !14) -!297 = !DILocation(line: 14, column: 11, scope: !2) -!298 = !DILocation(line: 14, column: 32, scope: !2) -!299 = !DILocation(line: 14, column: 34, scope: !2) -!300 = !DILocation(line: 14, column: 25, scope: !2) -!301 = !DILocation(line: 14, column: 15, scope: !2) -!302 = !DILocalVariable(name: "i", scope: !303, file: !3, line: 17, type: !6) -!303 = distinct !DILexicalBlock(scope: !2, file: !3, line: 17, column: 3) -!304 = !DILocation(line: 17, column: 12, scope: !303) -!305 = !DILocation(line: 17, column: 8, scope: !303) -!306 = !DILocation(line: 17, column: 19, scope: !307) -!307 = distinct !DILexicalBlock(scope: !303, file: !3, line: 17, column: 3) -!308 = !DILocation(line: 17, column: 23, scope: !307) -!309 = !DILocation(line: 17, column: 21, scope: !307) -!310 = !DILocation(line: 17, column: 3, scope: !303) -!311 = !DILocation(line: 18, column: 5, scope: !312) -!312 = distinct !DILexicalBlock(scope: !307, file: !3, line: 17, column: 31) -!313 = !DILocation(line: 18, column: 7, scope: !312) -!314 = !DILocation(line: 18, column: 10, scope: !312) -!315 = !DILocation(line: 19, column: 3, scope: !312) -!316 = !DILocation(line: 17, column: 27, scope: !307) -!317 = !DILocation(line: 17, column: 3, scope: !307) -!318 = distinct !{!318, !310, !319} -!319 = !DILocation(line: 19, column: 3, scope: !303) -!320 = !DILocalVariable(name: "k", scope: !321, file: !3, line: 20, type: !6) -!321 = distinct !DILexicalBlock(scope: !2, file: !3, line: 20, column: 3) -!322 = !DILocation(line: 20, column: 12, scope: !321) -!323 = !DILocation(line: 20, column: 8, scope: !321) -!324 = !DILocation(line: 20, column: 19, scope: !325) -!325 = distinct !DILexicalBlock(scope: !321, file: !3, line: 20, column: 3) -!326 = !DILocation(line: 20, column: 21, scope: !325) -!327 = !DILocation(line: 20, column: 3, scope: !321) -!328 = !DILocalVariable(name: "j", scope: !329, file: !3, line: 21, type: !6) -!329 = distinct !DILexicalBlock(scope: !330, file: !3, line: 21, column: 5) -!330 = distinct !DILexicalBlock(scope: !325, file: !3, line: 20, column: 32) -!331 = !DILocation(line: 21, column: 14, scope: !329) -!332 = !DILocation(line: 21, column: 10, scope: !329) -!333 = !DILocation(line: 21, column: 21, scope: !334) -!334 = distinct !DILexicalBlock(scope: !329, file: !3, line: 21, column: 5) -!335 = !DILocation(line: 21, column: 23, scope: !334) -!336 = !DILocation(line: 21, column: 5, scope: !329) -!337 = !DILocalVariable(name: "i", scope: !338, file: !3, line: 22, type: !6) -!338 = distinct !DILexicalBlock(scope: !339, file: !3, line: 22, column: 7) -!339 = distinct !DILexicalBlock(scope: !334, file: !3, line: 21, column: 34) -!340 = !DILocation(line: 22, column: 16, scope: !338) -!341 = !DILocation(line: 22, column: 12, scope: !338) -!342 = !DILocation(line: 22, column: 23, scope: !343) -!343 = distinct !DILexicalBlock(scope: !338, file: !3, line: 22, column: 7) -!344 = !DILocation(line: 22, column: 27, scope: !343) -!345 = !DILocation(line: 22, column: 29, scope: !343) -!346 = !DILocation(line: 22, column: 25, scope: !343) -!347 = !DILocation(line: 22, column: 7, scope: !338) -!348 = !DILocalVariable(name: "sum", scope: !349, file: !3, line: 23, type: !6) -!349 = distinct !DILexicalBlock(scope: !343, file: !3, line: 22, column: 47) -!350 = !DILocation(line: 23, column: 13, scope: !349) -!351 = !DILocation(line: 23, column: 34, scope: !349) -!352 = !DILocation(line: 23, column: 38, scope: !349) -!353 = !DILocation(line: 23, column: 43, scope: !349) -!354 = !DILocation(line: 23, column: 45, scope: !349) -!355 = !DILocation(line: 23, column: 40, scope: !349) -!356 = !DILocation(line: 23, column: 36, scope: !349) -!357 = !DILocation(line: 23, column: 53, scope: !349) -!358 = !DILocation(line: 23, column: 58, scope: !349) -!359 = !DILocation(line: 23, column: 60, scope: !349) -!360 = !DILocation(line: 23, column: 55, scope: !349) -!361 = !DILocation(line: 23, column: 51, scope: !349) -!362 = !DILocation(line: 23, column: 75, scope: !349) -!363 = !DILocation(line: 23, column: 73, scope: !349) -!364 = !DILocation(line: 23, column: 79, scope: !349) -!365 = !DILocation(line: 23, column: 81, scope: !349) -!366 = !DILocation(line: 23, column: 96, scope: !349) -!367 = !DILocation(line: 23, column: 94, scope: !349) -!368 = !DILocation(line: 23, column: 19, scope: !349) -!369 = !DILocation(line: 24, column: 7, scope: !349) -!370 = !DILocation(line: 22, column: 42, scope: !343) -!371 = !DILocation(line: 22, column: 7, scope: !343) -!372 = distinct !{!372, !347, !373} -!373 = !DILocation(line: 24, column: 7, scope: !338) -!374 = !DILocation(line: 25, column: 5, scope: !339) -!375 = !DILocation(line: 21, column: 30, scope: !334) -!376 = !DILocation(line: 21, column: 5, scope: !334) -!377 = distinct !{!377, !336, !378} -!378 = !DILocation(line: 25, column: 5, scope: !329) -!379 = !DILocation(line: 26, column: 3, scope: !330) -!380 = !DILocation(line: 20, column: 28, scope: !325) -!381 = !DILocation(line: 20, column: 3, scope: !325) -!382 = distinct !{!382, !327, !383} -!383 = !DILocation(line: 26, column: 3, scope: !321) -!384 = !DILocation(line: 28, column: 8, scope: !2) -!385 = !DILocation(line: 28, column: 3, scope: !2) -!386 = !DILocation(line: 29, column: 3, scope: !2) diff --git a/test/end_to_end/do_all/calls/allowing/src/FileMapping.txt b/test/end_to_end/do_all/calls/allowing/src/FileMapping.txt deleted file mode 100644 index ee9f5f73c..000000000 --- a/test/end_to_end/do_all/calls/allowing/src/FileMapping.txt +++ /dev/null @@ -1 +0,0 @@ -1 /home/lukas/git/discopop/test/end_to_end/do_all/calls/allowing/src/code.cpp diff --git a/test/end_to_end/do_all/calls/allowing/src/code.ll b/test/end_to_end/do_all/calls/allowing/src/code.ll deleted file mode 100644 index 69bd58872..000000000 --- a/test/end_to_end/do_all/calls/allowing/src/code.ll +++ /dev/null @@ -1,552 +0,0 @@ -; ModuleID = 'code.cpp' -source_filename = "code.cpp" -target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-unknown-linux-gnu" - -@_ZZ4mainE1n = internal global i32 1000, align 4, !dbg !0 -@.str = private unnamed_addr constant [4 x i8] c"tmp\00", align 1 -@.str.1 = private unnamed_addr constant [2 x i8] c"i\00", align 1 -@.str.2 = private unnamed_addr constant [2 x i8] c"z\00", align 1 -@.str.3 = private unnamed_addr constant [10 x i8] c"1:10;1:11\00", align 1 -@.str.4 = private unnamed_addr constant [10 x i8] c"1:10;1:12\00", align 1 -@.str.5 = private unnamed_addr constant [10 x i8] c"1:10;1:15\00", align 1 -@.str.6 = private unnamed_addr constant [12 x i8] c"_ZZ4mainE1n\00", align 1 -@.str.7 = private unnamed_addr constant [5 x i8] c".str\00", align 1 -@.str.8 = private unnamed_addr constant [7 x i8] c".str.1\00", align 1 -@.str.9 = private unnamed_addr constant [7 x i8] c".str.2\00", align 1 -@.str.10 = private unnamed_addr constant [7 x i8] c".str.3\00", align 1 -@.str.11 = private unnamed_addr constant [7 x i8] c".str.4\00", align 1 -@.str.12 = private unnamed_addr constant [7 x i8] c"retval\00", align 1 -@.str.13 = private unnamed_addr constant [5 x i8] c"argc\00", align 1 -@.str.14 = private unnamed_addr constant [5 x i8] c"argv\00", align 1 -@.str.15 = private unnamed_addr constant [2 x i8] c"x\00", align 1 - -; Function Attrs: noinline nounwind optnone uwtable -define void @_Z14allowing_doallPdi(double* %tmp, i32 %i) #0 !dbg !263 { -entry: - call void @__dp_func_entry(i32 16388, i32 0) - %tmp.addr = alloca double*, align 8 - %0 = ptrtoint double** %tmp.addr to i64 - %i.addr = alloca i32, align 4 - %1 = ptrtoint i32* %i.addr to i64 - %z = alloca i32, align 4 - %2 = ptrtoint i32* %z to i64 - %3 = ptrtoint double** %tmp.addr to i64 - store double* %tmp, double** %tmp.addr, align 8 - call void @llvm.dbg.declare(metadata double** %tmp.addr, metadata !266, metadata !DIExpression()), !dbg !267 - %4 = ptrtoint i32* %i.addr to i64 - store i32 %i, i32* %i.addr, align 4 - call void @llvm.dbg.declare(metadata i32* %i.addr, metadata !268, metadata !DIExpression()), !dbg !269 - call void @llvm.dbg.declare(metadata i32* %z, metadata !270, metadata !DIExpression()), !dbg !271 - %5 = ptrtoint i32* %i.addr to i64 - %6 = load i32, i32* %i.addr, align 4, !dbg !272 - %conv = sitofp i32 %6 to double, !dbg !272 - %7 = ptrtoint double** %tmp.addr to i64 - %8 = load double*, double** %tmp.addr, align 8, !dbg !273 - %9 = ptrtoint i32* %i.addr to i64 - %10 = load i32, i32* %i.addr, align 4, !dbg !274 - %idxprom = sext i32 %10 to i64, !dbg !273 - %arrayidx = getelementptr inbounds double, double* %8, i64 %idxprom, !dbg !273 - %11 = ptrtoint double* %arrayidx to i64 - call void @__dp_read(i32 16389, i64 %11, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0)) - %12 = load double, double* %arrayidx, align 8, !dbg !273 - %add = fadd double %conv, %12, !dbg !275 - %conv1 = fptosi double %add to i32, !dbg !272 - %13 = ptrtoint i32* %z to i64 - store i32 %conv1, i32* %z, align 4, !dbg !271 - %14 = ptrtoint i32* %z to i64 - %15 = load i32, i32* %z, align 4, !dbg !276 - %add2 = add nsw i32 %15, 2, !dbg !277 - %conv3 = sitofp i32 %add2 to double, !dbg !276 - %16 = ptrtoint double** %tmp.addr to i64 - %17 = load double*, double** %tmp.addr, align 8, !dbg !278 - %18 = ptrtoint i32* %i.addr to i64 - %19 = load i32, i32* %i.addr, align 4, !dbg !279 - %idxprom4 = sext i32 %19 to i64, !dbg !278 - %arrayidx5 = getelementptr inbounds double, double* %17, i64 %idxprom4, !dbg !278 - %20 = ptrtoint double* %arrayidx5 to i64 - call void @__dp_write(i32 16390, i64 %20, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0)) - store double %conv3, double* %arrayidx5, align 8, !dbg !280 - call void @__dp_report_bb(i32 0) - call void @__dp_func_exit(i32 16391, i32 0), !dbg !281 - ret void, !dbg !281 -} - -; Function Attrs: nounwind readnone speculatable willreturn -declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 - -; Function Attrs: noinline norecurse nounwind optnone uwtable -define i32 @main(i32 %argc, i8** %argv) #2 !dbg !2 { -entry: - call void @__dp_func_entry(i32 16393, i32 1) - %__dp_bb = alloca i32, align 4 - store i32 0, i32* %__dp_bb, align 4 - %retval = alloca i32, align 4 - %0 = ptrtoint i32* %retval to i64 - %argc.addr = alloca i32, align 4 - %1 = ptrtoint i32* %argc.addr to i64 - %argv.addr = alloca i8**, align 8 - %2 = ptrtoint i8*** %argv.addr to i64 - %x = alloca double*, align 8 - %3 = ptrtoint double** %x to i64 - %i = alloca i32, align 4 - %4 = ptrtoint i32* %i to i64 - %5 = ptrtoint i32* %retval to i64 - store i32 0, i32* %retval, align 4 - %6 = ptrtoint i32* %argc.addr to i64 - store i32 %argc, i32* %argc.addr, align 4 - call void @llvm.dbg.declare(metadata i32* %argc.addr, metadata !282, metadata !DIExpression()), !dbg !283 - %7 = ptrtoint i8*** %argv.addr to i64 - store i8** %argv, i8*** %argv.addr, align 8 - call void @llvm.dbg.declare(metadata i8*** %argv.addr, metadata !284, metadata !DIExpression()), !dbg !285 - call void @llvm.dbg.declare(metadata double** %x, metadata !286, metadata !DIExpression()), !dbg !287 - %8 = ptrtoint i32* @_ZZ4mainE1n to i64 - call void @__dp_read(i32 16395, i64 %8, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.6, i32 0, i32 0)) - %9 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !288 - %conv = sext i32 %9 to i64, !dbg !288 - %mul = mul i64 %conv, 8, !dbg !289 - %call = call noalias i8* @malloc(i64 %mul) #4, !dbg !290 - %10 = ptrtoint i8* %call to i64 - call void @__dp_new(i32 16395, i64 %10, i64 %10, i64 %mul), !dbg !291 - %11 = bitcast i8* %call to double*, !dbg !291 - %12 = ptrtoint double** %x to i64 - store double* %11, double** %x, align 8, !dbg !287 - call void @llvm.dbg.declare(metadata i32* %i, metadata !292, metadata !DIExpression()), !dbg !294 - %13 = ptrtoint i32* %i to i64 - store i32 0, i32* %i, align 4, !dbg !294 - call void @__dp_report_bb(i32 1) - br label %for.cond, !dbg !295 - -for.cond: ; preds = %for.inc, %entry - call void @__dp_loop_entry(i32 16398, i32 0) - %14 = ptrtoint i32* %i to i64 - %15 = load i32, i32* %i, align 4, !dbg !296 - %16 = ptrtoint i32* @_ZZ4mainE1n to i64 - call void @__dp_read(i32 16398, i64 %16, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.6, i32 0, i32 0)) - %17 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !298 - %cmp = icmp slt i32 %15, %17, !dbg !299 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.3, i32 0, i32 0), i1 %cmp, i32 1), !dbg !300 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.4, i32 0, i32 0), i1 %cmp, i32 1), !dbg !300 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.5, i32 0, i32 0), i1 %cmp, i32 0), !dbg !300 - call void @__dp_report_bb(i32 3) - %18 = load i32, i32* %__dp_bb, align 4 - call void @__dp_report_bb_pair(i32 %18, i32 6) - br i1 %cmp, label %for.body, label %for.end, !dbg !300 - -for.body: ; preds = %for.cond - call void @__dp_loop_incr(i32 1) - %19 = ptrtoint double** %x to i64 - %20 = load double*, double** %x, align 8, !dbg !301 - %21 = ptrtoint i32* %i to i64 - %22 = load i32, i32* %i, align 4, !dbg !303 - %idxprom = sext i32 %22 to i64, !dbg !301 - %arrayidx = getelementptr inbounds double, double* %20, i64 %idxprom, !dbg !301 - %23 = ptrtoint double* %arrayidx to i64 - call void @__dp_write(i32 16399, i64 %23, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.15, i32 0, i32 0)) - store double 1.000000e+00, double* %arrayidx, align 8, !dbg !304 - %24 = ptrtoint double** %x to i64 - %25 = load double*, double** %x, align 8, !dbg !305 - %26 = ptrtoint i32* %i to i64 - %27 = load i32, i32* %i, align 4, !dbg !306 - call void @__dp_call(i32 16400), !dbg !307 - call void @_Z14allowing_doallPdi(double* %25, i32 %27), !dbg !307 - call void @__dp_report_bb(i32 5) - %28 = load i32, i32* %__dp_bb, align 4 - call void @__dp_report_bb_pair(i32 %28, i32 8) - br label %for.inc, !dbg !308 - -for.inc: ; preds = %for.body - %29 = ptrtoint i32* %i to i64 - %30 = load i32, i32* %i, align 4, !dbg !309 - %inc = add nsw i32 %30, 1, !dbg !309 - %31 = ptrtoint i32* %i to i64 - store i32 %inc, i32* %i, align 4, !dbg !309 - call void @__dp_report_bb(i32 4) - %32 = load i32, i32* %__dp_bb, align 4 - call void @__dp_report_bb_pair(i32 %32, i32 7) - store i32 1, i32* %__dp_bb, align 4 - br label %for.cond, !dbg !310, !llvm.loop !311 - -for.end: ; preds = %for.cond - call void @__dp_loop_exit(i32 16402, i32 0) - %33 = ptrtoint double** %x to i64 - %34 = load double*, double** %x, align 8, !dbg !313 - %35 = bitcast double* %34 to i8*, !dbg !313 - call void @free(i8* %35) #4, !dbg !314 - %36 = ptrtoint i8* %35 to i64 - call void @__dp_delete(i32 16402, i64 %36), !dbg !315 - call void @__dp_report_bb(i32 2) - call void @__dp_finalize(i32 16403), !dbg !315 - call void @__dp_loop_output(), !dbg !315 - call void @__dp_taken_branch_counter_output(), !dbg !315 - ret i32 0, !dbg !315 -} - -; Function Attrs: nounwind -declare noalias i8* @malloc(i64) #3 - -; Function Attrs: nounwind -declare void @free(i8*) #3 - -declare void @__dp_init(i32, i32, i32) - -declare void @__dp_finalize(i32) - -declare void @__dp_read(i32, i64, i8*) - -declare void @__dp_write(i32, i64, i8*) - -declare void @__dp_alloca(i32, i8*, i64, i64, i64, i64) - -declare void @__dp_new(i32, i64, i64, i64) - -declare void @__dp_delete(i32, i64) - -declare void @__dp_call(i32) - -declare void @__dp_func_entry(i32, i32) - -declare void @__dp_func_exit(i32, i32) - -declare void @__dp_loop_entry(i32, i32) - -declare void @__dp_loop_exit(i32, i32) - -declare void @__dp_incr_taken_branch_counter(i8*, i32, i32) - -declare void @__dp_report_bb(i32) - -declare void @__dp_report_bb_pair(i32, i32) - -declare void @__dp_loop_incr(i32) - -declare void @__dp_loop_output() - -declare void @__dp_taken_branch_counter_output() - -attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { nounwind readnone speculatable willreturn } -attributes #2 = { noinline norecurse nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #3 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #4 = { nounwind } - -!llvm.dbg.cu = !{!11} -!llvm.module.flags = !{!258, !259, !260, !261} -!llvm.ident = !{!262} - -!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) -!1 = distinct !DIGlobalVariable(name: "n", scope: !2, file: !3, line: 10, type: !6, isLocal: true, isDefinition: true) -!2 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 9, type: !4, scopeLine: 9, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !11, retainedNodes: !12) -!3 = !DIFile(filename: "code.cpp", directory: "/home/lukas/git/discopop/test/end_to_end/do_all/calls/allowing/src") -!4 = !DISubroutineType(types: !5) -!5 = !{!6, !6, !7} -!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) -!7 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64) -!8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64) -!9 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !10) -!10 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) -!11 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 11.1.0 (https://github.com/llvm/llvm-project.git 7e99bddfeaab2713a8bb6ca538da25b66e6efc59)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !12, retainedTypes: !13, globals: !16, imports: !17, splitDebugInlining: false, nameTableKind: None) -!12 = !{} -!13 = !{!14} -!14 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !15, size: 64) -!15 = !DIBasicType(name: "double", size: 64, encoding: DW_ATE_float) -!16 = !{!0} -!17 = !{!18, !25, !29, !36, !40, !45, !47, !51, !55, !59, !73, !77, !81, !85, !89, !94, !98, !102, !106, !110, !118, !122, !126, !128, !132, !136, !141, !147, !151, !155, !157, !165, !169, !177, !179, !183, !187, !191, !195, !200, !205, !210, !211, !212, !213, !215, !216, !217, !218, !219, !220, !221, !223, !224, !225, !226, !227, !228, !229, !234, !235, !236, !237, !238, !239, !240, !241, !242, !243, !244, !245, !246, !247, !248, !249, !250, !251, !252, !253, !254, !255, !256, !257} -!18 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !20, file: !24, line: 52) -!19 = !DINamespace(name: "std", scope: null) -!20 = !DISubprogram(name: "abs", scope: !21, file: !21, line: 848, type: !22, flags: DIFlagPrototyped, spFlags: 0) -!21 = !DIFile(filename: "/usr/include/stdlib.h", directory: "") -!22 = !DISubroutineType(types: !23) -!23 = !{!6, !6} -!24 = !DIFile(filename: "/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/bits/std_abs.h", directory: "") -!25 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !26, file: !28, line: 127) -!26 = !DIDerivedType(tag: DW_TAG_typedef, name: "div_t", file: !21, line: 63, baseType: !27) -!27 = !DICompositeType(tag: DW_TAG_structure_type, file: !21, line: 59, flags: DIFlagFwdDecl, identifier: "_ZTS5div_t") -!28 = !DIFile(filename: "/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/cstdlib", directory: "") -!29 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !30, file: !28, line: 128) -!30 = !DIDerivedType(tag: DW_TAG_typedef, name: "ldiv_t", file: !21, line: 71, baseType: !31) -!31 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !21, line: 67, size: 128, flags: DIFlagTypePassByValue, elements: !32, identifier: "_ZTS6ldiv_t") -!32 = !{!33, !35} -!33 = !DIDerivedType(tag: DW_TAG_member, name: "quot", scope: !31, file: !21, line: 69, baseType: !34, size: 64) -!34 = !DIBasicType(name: "long int", size: 64, encoding: DW_ATE_signed) -!35 = !DIDerivedType(tag: DW_TAG_member, name: "rem", scope: !31, file: !21, line: 70, baseType: !34, size: 64, offset: 64) -!36 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !37, file: !28, line: 130) -!37 = !DISubprogram(name: "abort", scope: !21, file: !21, line: 598, type: !38, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) -!38 = !DISubroutineType(types: !39) -!39 = !{null} -!40 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !41, file: !28, line: 134) -!41 = !DISubprogram(name: "atexit", scope: !21, file: !21, line: 602, type: !42, flags: DIFlagPrototyped, spFlags: 0) -!42 = !DISubroutineType(types: !43) -!43 = !{!6, !44} -!44 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !38, size: 64) -!45 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !46, file: !28, line: 137) -!46 = !DISubprogram(name: "at_quick_exit", scope: !21, file: !21, line: 607, type: !42, flags: DIFlagPrototyped, spFlags: 0) -!47 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !48, file: !28, line: 140) -!48 = !DISubprogram(name: "atof", scope: !21, file: !21, line: 102, type: !49, flags: DIFlagPrototyped, spFlags: 0) -!49 = !DISubroutineType(types: !50) -!50 = !{!15, !8} -!51 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !52, file: !28, line: 141) -!52 = !DISubprogram(name: "atoi", scope: !21, file: !21, line: 105, type: !53, flags: DIFlagPrototyped, spFlags: 0) -!53 = !DISubroutineType(types: !54) -!54 = !{!6, !8} -!55 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !56, file: !28, line: 142) -!56 = !DISubprogram(name: "atol", scope: !21, file: !21, line: 108, type: !57, flags: DIFlagPrototyped, spFlags: 0) -!57 = !DISubroutineType(types: !58) -!58 = !{!34, !8} -!59 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !60, file: !28, line: 143) -!60 = !DISubprogram(name: "bsearch", scope: !21, file: !21, line: 828, type: !61, flags: DIFlagPrototyped, spFlags: 0) -!61 = !DISubroutineType(types: !62) -!62 = !{!63, !64, !64, !66, !66, !69} -!63 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) -!64 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !65, size: 64) -!65 = !DIDerivedType(tag: DW_TAG_const_type, baseType: null) -!66 = !DIDerivedType(tag: DW_TAG_typedef, name: "size_t", file: !67, line: 46, baseType: !68) -!67 = !DIFile(filename: "Software/llvm-11.1.0/lib/clang/11.1.0/include/stddef.h", directory: "/home/lukas") -!68 = !DIBasicType(name: "long unsigned int", size: 64, encoding: DW_ATE_unsigned) -!69 = !DIDerivedType(tag: DW_TAG_typedef, name: "__compar_fn_t", file: !21, line: 816, baseType: !70) -!70 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !71, size: 64) -!71 = !DISubroutineType(types: !72) -!72 = !{!6, !64, !64} -!73 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !74, file: !28, line: 144) -!74 = !DISubprogram(name: "calloc", scope: !21, file: !21, line: 543, type: !75, flags: DIFlagPrototyped, spFlags: 0) -!75 = !DISubroutineType(types: !76) -!76 = !{!63, !66, !66} -!77 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !78, file: !28, line: 145) -!78 = !DISubprogram(name: "div", scope: !21, file: !21, line: 860, type: !79, flags: DIFlagPrototyped, spFlags: 0) -!79 = !DISubroutineType(types: !80) -!80 = !{!26, !6, !6} -!81 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !82, file: !28, line: 146) -!82 = !DISubprogram(name: "exit", scope: !21, file: !21, line: 624, type: !83, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) -!83 = !DISubroutineType(types: !84) -!84 = !{null, !6} -!85 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !86, file: !28, line: 147) -!86 = !DISubprogram(name: "free", scope: !21, file: !21, line: 555, type: !87, flags: DIFlagPrototyped, spFlags: 0) -!87 = !DISubroutineType(types: !88) -!88 = !{null, !63} -!89 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !90, file: !28, line: 148) -!90 = !DISubprogram(name: "getenv", scope: !21, file: !21, line: 641, type: !91, flags: DIFlagPrototyped, spFlags: 0) -!91 = !DISubroutineType(types: !92) -!92 = !{!93, !8} -!93 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64) -!94 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !95, file: !28, line: 149) -!95 = !DISubprogram(name: "labs", scope: !21, file: !21, line: 849, type: !96, flags: DIFlagPrototyped, spFlags: 0) -!96 = !DISubroutineType(types: !97) -!97 = !{!34, !34} -!98 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !99, file: !28, line: 150) -!99 = !DISubprogram(name: "ldiv", scope: !21, file: !21, line: 862, type: !100, flags: DIFlagPrototyped, spFlags: 0) -!100 = !DISubroutineType(types: !101) -!101 = !{!30, !34, !34} -!102 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !103, file: !28, line: 151) -!103 = !DISubprogram(name: "malloc", scope: !21, file: !21, line: 540, type: !104, flags: DIFlagPrototyped, spFlags: 0) -!104 = !DISubroutineType(types: !105) -!105 = !{!63, !66} -!106 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !107, file: !28, line: 153) -!107 = !DISubprogram(name: "mblen", scope: !21, file: !21, line: 930, type: !108, flags: DIFlagPrototyped, spFlags: 0) -!108 = !DISubroutineType(types: !109) -!109 = !{!6, !8, !66} -!110 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !111, file: !28, line: 154) -!111 = !DISubprogram(name: "mbstowcs", scope: !21, file: !21, line: 941, type: !112, flags: DIFlagPrototyped, spFlags: 0) -!112 = !DISubroutineType(types: !113) -!113 = !{!66, !114, !117, !66} -!114 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !115) -!115 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !116, size: 64) -!116 = !DIBasicType(name: "wchar_t", size: 32, encoding: DW_ATE_signed) -!117 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !8) -!118 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !119, file: !28, line: 155) -!119 = !DISubprogram(name: "mbtowc", scope: !21, file: !21, line: 933, type: !120, flags: DIFlagPrototyped, spFlags: 0) -!120 = !DISubroutineType(types: !121) -!121 = !{!6, !114, !117, !66} -!122 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !123, file: !28, line: 157) -!123 = !DISubprogram(name: "qsort", scope: !21, file: !21, line: 838, type: !124, flags: DIFlagPrototyped, spFlags: 0) -!124 = !DISubroutineType(types: !125) -!125 = !{null, !63, !66, !66, !69} -!126 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !127, file: !28, line: 160) -!127 = !DISubprogram(name: "quick_exit", scope: !21, file: !21, line: 630, type: !83, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) -!128 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !129, file: !28, line: 163) -!129 = !DISubprogram(name: "rand", scope: !21, file: !21, line: 454, type: !130, flags: DIFlagPrototyped, spFlags: 0) -!130 = !DISubroutineType(types: !131) -!131 = !{!6} -!132 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !133, file: !28, line: 164) -!133 = !DISubprogram(name: "realloc", scope: !21, file: !21, line: 551, type: !134, flags: DIFlagPrototyped, spFlags: 0) -!134 = !DISubroutineType(types: !135) -!135 = !{!63, !63, !66} -!136 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !137, file: !28, line: 165) -!137 = !DISubprogram(name: "srand", scope: !21, file: !21, line: 456, type: !138, flags: DIFlagPrototyped, spFlags: 0) -!138 = !DISubroutineType(types: !139) -!139 = !{null, !140} -!140 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned) -!141 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !142, file: !28, line: 166) -!142 = !DISubprogram(name: "strtod", scope: !21, file: !21, line: 118, type: !143, flags: DIFlagPrototyped, spFlags: 0) -!143 = !DISubroutineType(types: !144) -!144 = !{!15, !117, !145} -!145 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !146) -!146 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !93, size: 64) -!147 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !148, file: !28, line: 167) -!148 = !DISubprogram(name: "strtol", scope: !21, file: !21, line: 177, type: !149, flags: DIFlagPrototyped, spFlags: 0) -!149 = !DISubroutineType(types: !150) -!150 = !{!34, !117, !145, !6} -!151 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !152, file: !28, line: 168) -!152 = !DISubprogram(name: "strtoul", scope: !21, file: !21, line: 181, type: !153, flags: DIFlagPrototyped, spFlags: 0) -!153 = !DISubroutineType(types: !154) -!154 = !{!68, !117, !145, !6} -!155 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !156, file: !28, line: 169) -!156 = !DISubprogram(name: "system", scope: !21, file: !21, line: 791, type: !53, flags: DIFlagPrototyped, spFlags: 0) -!157 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !158, file: !28, line: 171) -!158 = !DISubprogram(name: "wcstombs", scope: !21, file: !21, line: 945, type: !159, flags: DIFlagPrototyped, spFlags: 0) -!159 = !DISubroutineType(types: !160) -!160 = !{!66, !161, !162, !66} -!161 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !93) -!162 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !163) -!163 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !164, size: 64) -!164 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !116) -!165 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !166, file: !28, line: 172) -!166 = !DISubprogram(name: "wctomb", scope: !21, file: !21, line: 937, type: !167, flags: DIFlagPrototyped, spFlags: 0) -!167 = !DISubroutineType(types: !168) -!168 = !{!6, !93, !116} -!169 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !171, file: !28, line: 200) -!170 = !DINamespace(name: "__gnu_cxx", scope: null) -!171 = !DIDerivedType(tag: DW_TAG_typedef, name: "lldiv_t", file: !21, line: 81, baseType: !172) -!172 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !21, line: 77, size: 128, flags: DIFlagTypePassByValue, elements: !173, identifier: "_ZTS7lldiv_t") -!173 = !{!174, !176} -!174 = !DIDerivedType(tag: DW_TAG_member, name: "quot", scope: !172, file: !21, line: 79, baseType: !175, size: 64) -!175 = !DIBasicType(name: "long long int", size: 64, encoding: DW_ATE_signed) -!176 = !DIDerivedType(tag: DW_TAG_member, name: "rem", scope: !172, file: !21, line: 80, baseType: !175, size: 64, offset: 64) -!177 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !178, file: !28, line: 206) -!178 = !DISubprogram(name: "_Exit", scope: !21, file: !21, line: 636, type: !83, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) -!179 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !180, file: !28, line: 210) -!180 = !DISubprogram(name: "llabs", scope: !21, file: !21, line: 852, type: !181, flags: DIFlagPrototyped, spFlags: 0) -!181 = !DISubroutineType(types: !182) -!182 = !{!175, !175} -!183 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !184, file: !28, line: 216) -!184 = !DISubprogram(name: "lldiv", scope: !21, file: !21, line: 866, type: !185, flags: DIFlagPrototyped, spFlags: 0) -!185 = !DISubroutineType(types: !186) -!186 = !{!171, !175, !175} -!187 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !188, file: !28, line: 227) -!188 = !DISubprogram(name: "atoll", scope: !21, file: !21, line: 113, type: !189, flags: DIFlagPrototyped, spFlags: 0) -!189 = !DISubroutineType(types: !190) -!190 = !{!175, !8} -!191 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !192, file: !28, line: 228) -!192 = !DISubprogram(name: "strtoll", scope: !21, file: !21, line: 201, type: !193, flags: DIFlagPrototyped, spFlags: 0) -!193 = !DISubroutineType(types: !194) -!194 = !{!175, !117, !145, !6} -!195 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !196, file: !28, line: 229) -!196 = !DISubprogram(name: "strtoull", scope: !21, file: !21, line: 206, type: !197, flags: DIFlagPrototyped, spFlags: 0) -!197 = !DISubroutineType(types: !198) -!198 = !{!199, !117, !145, !6} -!199 = !DIBasicType(name: "long long unsigned int", size: 64, encoding: DW_ATE_unsigned) -!200 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !201, file: !28, line: 231) -!201 = !DISubprogram(name: "strtof", scope: !21, file: !21, line: 124, type: !202, flags: DIFlagPrototyped, spFlags: 0) -!202 = !DISubroutineType(types: !203) -!203 = !{!204, !117, !145} -!204 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) -!205 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !170, entity: !206, file: !28, line: 232) -!206 = !DISubprogram(name: "strtold", scope: !21, file: !21, line: 127, type: !207, flags: DIFlagPrototyped, spFlags: 0) -!207 = !DISubroutineType(types: !208) -!208 = !{!209, !117, !145} -!209 = !DIBasicType(name: "long double", size: 128, encoding: DW_ATE_float) -!210 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !171, file: !28, line: 240) -!211 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !178, file: !28, line: 242) -!212 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !180, file: !28, line: 244) -!213 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !214, file: !28, line: 245) -!214 = !DISubprogram(name: "div", linkageName: "_ZN9__gnu_cxx3divExx", scope: !170, file: !28, line: 213, type: !185, flags: DIFlagPrototyped, spFlags: 0) -!215 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !184, file: !28, line: 246) -!216 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !188, file: !28, line: 248) -!217 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !201, file: !28, line: 249) -!218 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !192, file: !28, line: 250) -!219 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !196, file: !28, line: 251) -!220 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !19, entity: !206, file: !28, line: 252) -!221 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !37, file: !222, line: 38) -!222 = !DIFile(filename: "/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/stdlib.h", directory: "") -!223 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !41, file: !222, line: 39) -!224 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !82, file: !222, line: 40) -!225 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !46, file: !222, line: 43) -!226 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !127, file: !222, line: 46) -!227 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !26, file: !222, line: 51) -!228 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !30, file: !222, line: 52) -!229 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !230, file: !222, line: 54) -!230 = !DISubprogram(name: "abs", linkageName: "_ZSt3absg", scope: !19, file: !24, line: 103, type: !231, flags: DIFlagPrototyped, spFlags: 0) -!231 = !DISubroutineType(types: !232) -!232 = !{!233, !233} -!233 = !DIBasicType(name: "__float128", size: 128, encoding: DW_ATE_float) -!234 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !48, file: !222, line: 55) -!235 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !52, file: !222, line: 56) -!236 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !56, file: !222, line: 57) -!237 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !60, file: !222, line: 58) -!238 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !74, file: !222, line: 59) -!239 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !214, file: !222, line: 60) -!240 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !86, file: !222, line: 61) -!241 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !90, file: !222, line: 62) -!242 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !95, file: !222, line: 63) -!243 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !99, file: !222, line: 64) -!244 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !103, file: !222, line: 65) -!245 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !107, file: !222, line: 67) -!246 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !111, file: !222, line: 68) -!247 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !119, file: !222, line: 69) -!248 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !123, file: !222, line: 71) -!249 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !129, file: !222, line: 72) -!250 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !133, file: !222, line: 73) -!251 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !137, file: !222, line: 74) -!252 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !142, file: !222, line: 75) -!253 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !148, file: !222, line: 76) -!254 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !152, file: !222, line: 77) -!255 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !156, file: !222, line: 78) -!256 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !158, file: !222, line: 80) -!257 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !166, file: !222, line: 81) -!258 = !{i32 7, !"Dwarf Version", i32 4} -!259 = !{i32 2, !"Debug Info Version", i32 3} -!260 = !{i32 1, !"wchar_size", i32 4} -!261 = !{i32 7, !"PIC Level", i32 2} -!262 = !{!"clang version 11.1.0 (https://github.com/llvm/llvm-project.git 7e99bddfeaab2713a8bb6ca538da25b66e6efc59)"} -!263 = distinct !DISubprogram(name: "allowing_doall", linkageName: "_Z14allowing_doallPdi", scope: !3, file: !3, line: 4, type: !264, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !11, retainedNodes: !12) -!264 = !DISubroutineType(types: !265) -!265 = !{null, !14, !6} -!266 = !DILocalVariable(name: "tmp", arg: 1, scope: !263, file: !3, line: 4, type: !14) -!267 = !DILocation(line: 4, column: 29, scope: !263) -!268 = !DILocalVariable(name: "i", arg: 2, scope: !263, file: !3, line: 4, type: !6) -!269 = !DILocation(line: 4, column: 38, scope: !263) -!270 = !DILocalVariable(name: "z", scope: !263, file: !3, line: 5, type: !6) -!271 = !DILocation(line: 5, column: 7, scope: !263) -!272 = !DILocation(line: 5, column: 11, scope: !263) -!273 = !DILocation(line: 5, column: 15, scope: !263) -!274 = !DILocation(line: 5, column: 19, scope: !263) -!275 = !DILocation(line: 5, column: 13, scope: !263) -!276 = !DILocation(line: 6, column: 12, scope: !263) -!277 = !DILocation(line: 6, column: 14, scope: !263) -!278 = !DILocation(line: 6, column: 3, scope: !263) -!279 = !DILocation(line: 6, column: 7, scope: !263) -!280 = !DILocation(line: 6, column: 10, scope: !263) -!281 = !DILocation(line: 7, column: 1, scope: !263) -!282 = !DILocalVariable(name: "argc", arg: 1, scope: !2, file: !3, line: 9, type: !6) -!283 = !DILocation(line: 9, column: 14, scope: !2) -!284 = !DILocalVariable(name: "argv", arg: 2, scope: !2, file: !3, line: 9, type: !7) -!285 = !DILocation(line: 9, column: 32, scope: !2) -!286 = !DILocalVariable(name: "x", scope: !2, file: !3, line: 11, type: !14) -!287 = !DILocation(line: 11, column: 11, scope: !2) -!288 = !DILocation(line: 11, column: 32, scope: !2) -!289 = !DILocation(line: 11, column: 34, scope: !2) -!290 = !DILocation(line: 11, column: 25, scope: !2) -!291 = !DILocation(line: 11, column: 15, scope: !2) -!292 = !DILocalVariable(name: "i", scope: !293, file: !3, line: 14, type: !6) -!293 = distinct !DILexicalBlock(scope: !2, file: !3, line: 14, column: 3) -!294 = !DILocation(line: 14, column: 12, scope: !293) -!295 = !DILocation(line: 14, column: 8, scope: !293) -!296 = !DILocation(line: 14, column: 19, scope: !297) -!297 = distinct !DILexicalBlock(scope: !293, file: !3, line: 14, column: 3) -!298 = !DILocation(line: 14, column: 23, scope: !297) -!299 = !DILocation(line: 14, column: 21, scope: !297) -!300 = !DILocation(line: 14, column: 3, scope: !293) -!301 = !DILocation(line: 15, column: 5, scope: !302) -!302 = distinct !DILexicalBlock(scope: !297, file: !3, line: 14, column: 31) -!303 = !DILocation(line: 15, column: 7, scope: !302) -!304 = !DILocation(line: 15, column: 10, scope: !302) -!305 = !DILocation(line: 16, column: 20, scope: !302) -!306 = !DILocation(line: 16, column: 23, scope: !302) -!307 = !DILocation(line: 16, column: 5, scope: !302) -!308 = !DILocation(line: 17, column: 3, scope: !302) -!309 = !DILocation(line: 14, column: 26, scope: !297) -!310 = !DILocation(line: 14, column: 3, scope: !297) -!311 = distinct !{!311, !300, !312} -!312 = !DILocation(line: 17, column: 3, scope: !293) -!313 = !DILocation(line: 18, column: 8, scope: !2) -!314 = !DILocation(line: 18, column: 3, scope: !2) -!315 = !DILocation(line: 19, column: 3, scope: !2) diff --git a/test/end_to_end/optimizer/loop_collapse/positive/simple_1/src/FileMapping.txt b/test/end_to_end/optimizer/loop_collapse/positive/simple_1/src/FileMapping.txt deleted file mode 100644 index 982301711..000000000 --- a/test/end_to_end/optimizer/loop_collapse/positive/simple_1/src/FileMapping.txt +++ /dev/null @@ -1 +0,0 @@ -1 /home/lukas/git/discopop/test/end_to_end/optimizer/loop_collapse/positive/simple_1/src/code.cpp diff --git a/test/end_to_end/reduction_pattern/negative/case_1/src/FileMapping.txt b/test/end_to_end/reduction_pattern/negative/case_1/src/FileMapping.txt deleted file mode 100644 index 8b05d2182..000000000 --- a/test/end_to_end/reduction_pattern/negative/case_1/src/FileMapping.txt +++ /dev/null @@ -1 +0,0 @@ -1 /home/lukas/git/discopop/test/end_to_end/reduction_pattern/negative/case_1/src/code.cpp diff --git a/test/end_to_end/reduction_pattern/negative/case_1/src/code.ll b/test/end_to_end/reduction_pattern/negative/case_1/src/code.ll deleted file mode 100644 index 8a5836cf6..000000000 --- a/test/end_to_end/reduction_pattern/negative/case_1/src/code.ll +++ /dev/null @@ -1,427 +0,0 @@ -; ModuleID = 'code.cpp' -source_filename = "code.cpp" -target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-unknown-linux-gnu" - -@.str = private unnamed_addr constant [8 x i8] c"1:1;1:3\00", align 1 -@.str.1 = private unnamed_addr constant [8 x i8] c"1:1;1:5\00", align 1 -@.str.2 = private unnamed_addr constant [8 x i8] c"1:2;1:3\00", align 1 -@.str.3 = private unnamed_addr constant [8 x i8] c"1:2;1:5\00", align 1 -@.str.4 = private unnamed_addr constant [7 x i8] c"retval\00", align 1 -@.str.5 = private unnamed_addr constant [2 x i8] c"i\00", align 1 -@.str.6 = private unnamed_addr constant [10 x i8] c"1:15;1:16\00", align 1 -@.str.7 = private unnamed_addr constant [10 x i8] c"1:15;1:18\00", align 1 -@.str.8 = private unnamed_addr constant [10 x i8] c"1:15;1:19\00", align 1 -@.str.9 = private unnamed_addr constant [10 x i8] c"1:21;1:22\00", align 1 -@.str.10 = private unnamed_addr constant [10 x i8] c"1:21;1:26\00", align 1 -@.str.11 = private unnamed_addr constant [5 x i8] c".str\00", align 1 -@.str.12 = private unnamed_addr constant [7 x i8] c".str.1\00", align 1 -@.str.13 = private unnamed_addr constant [7 x i8] c".str.2\00", align 1 -@.str.14 = private unnamed_addr constant [7 x i8] c".str.3\00", align 1 -@.str.15 = private unnamed_addr constant [7 x i8] c".str.4\00", align 1 -@.str.16 = private unnamed_addr constant [7 x i8] c".str.5\00", align 1 -@.str.17 = private unnamed_addr constant [7 x i8] c".str.6\00", align 1 -@.str.18 = private unnamed_addr constant [7 x i8] c".str.7\00", align 1 -@.str.19 = private unnamed_addr constant [7 x i8] c".str.8\00", align 1 -@.str.20 = private unnamed_addr constant [7 x i8] c".str.9\00", align 1 -@.str.21 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1 -@.str.22 = private unnamed_addr constant [2 x i8] c"N\00", align 1 -@.str.23 = private unnamed_addr constant [12 x i8] c"saved_stack\00", align 1 -@.str.24 = private unnamed_addr constant [12 x i8] c"__vla_expr0\00", align 1 -@.str.25 = private unnamed_addr constant [2 x i8] c"w\00", align 1 -@.str.26 = private unnamed_addr constant [4 x i8] c"Arr\00", align 1 - -; Function Attrs: noinline nounwind optnone uwtable -define i32 @_Z1fi(i32 %i) #0 !dbg !8 { -entry: - call void @__dp_func_entry(i32 16387, i32 0) - %__dp_bb1 = alloca i32, align 4 - store i32 0, i32* %__dp_bb1, align 4 - %__dp_bb = alloca i32, align 4 - store i32 0, i32* %__dp_bb, align 4 - %retval = alloca i32, align 4 - %0 = ptrtoint i32* %retval to i64 - %i.addr = alloca i32, align 4 - %1 = ptrtoint i32* %i.addr to i64 - %2 = ptrtoint i32* %i.addr to i64 - store i32 %i, i32* %i.addr, align 4 - call void @llvm.dbg.declare(metadata i32* %i.addr, metadata !12, metadata !DIExpression()), !dbg !13 - %3 = ptrtoint i32* %i.addr to i64 - %4 = load i32, i32* %i.addr, align 4, !dbg !14 - %cmp = icmp slt i32 %4, 50000, !dbg !16 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0), i1 %cmp, i32 1), !dbg !17 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.1, i32 0, i32 0), i1 %cmp, i32 0), !dbg !17 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.2, i32 0, i32 0), i1 %cmp, i32 1), !dbg !17 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.3, i32 0, i32 0), i1 %cmp, i32 0), !dbg !17 - call void @__dp_report_bb(i32 0) - br i1 %cmp, label %if.then, label %if.else, !dbg !17 - -if.then: ; preds = %entry - %5 = ptrtoint i32* %i.addr to i64 - %6 = load i32, i32* %i.addr, align 4, !dbg !18 - %add = add nsw i32 %6, 50000, !dbg !20 - %7 = ptrtoint i32* %retval to i64 - store i32 %add, i32* %retval, align 4, !dbg !21 - call void @__dp_report_bb(i32 1) - store i32 1, i32* %__dp_bb, align 4 - br label %return, !dbg !21 - -if.else: ; preds = %entry - %8 = ptrtoint i32* %i.addr to i64 - %9 = load i32, i32* %i.addr, align 4, !dbg !22 - %10 = ptrtoint i32* %retval to i64 - store i32 %9, i32* %retval, align 4, !dbg !24 - call void @__dp_report_bb(i32 2) - store i32 1, i32* %__dp_bb1, align 4 - br label %return, !dbg !24 - -return: ; preds = %if.else, %if.then - %11 = ptrtoint i32* %retval to i64 - %12 = load i32, i32* %retval, align 4, !dbg !25 - %13 = load i32, i32* %__dp_bb, align 4 - call void @__dp_report_bb_pair(i32 %13, i32 3) - %14 = load i32, i32* %__dp_bb1, align 4 - call void @__dp_report_bb_pair(i32 %14, i32 4) - call void @__dp_func_exit(i32 16393, i32 0), !dbg !25 - ret i32 %12, !dbg !25 -} - -; Function Attrs: nounwind readnone speculatable willreturn -declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 - -; Function Attrs: noinline nounwind optnone uwtable -define i32 @_Z1gi(i32 %i) #0 !dbg !26 { -entry: - call void @__dp_func_entry(i32 16395, i32 0) - %i.addr = alloca i32, align 4 - %0 = ptrtoint i32* %i.addr to i64 - %1 = ptrtoint i32* %i.addr to i64 - store i32 %i, i32* %i.addr, align 4 - call void @llvm.dbg.declare(metadata i32* %i.addr, metadata !27, metadata !DIExpression()), !dbg !28 - %2 = ptrtoint i32* %i.addr to i64 - %3 = load i32, i32* %i.addr, align 4, !dbg !29 - call void @__dp_report_bb(i32 5) - call void @__dp_func_exit(i32 16395, i32 0), !dbg !30 - ret i32 %3, !dbg !30 -} - -; Function Attrs: noinline norecurse nounwind optnone uwtable -define i32 @main() #2 !dbg !31 { -entry: - call void @__dp_func_entry(i32 16397, i32 1) - %__dp_bb14 = alloca i32, align 4 - store i32 0, i32* %__dp_bb14, align 4 - %__dp_bb13 = alloca i32, align 4 - store i32 0, i32* %__dp_bb13, align 4 - %__dp_bb = alloca i32, align 4 - store i32 0, i32* %__dp_bb, align 4 - %retval = alloca i32, align 4 - %0 = ptrtoint i32* %retval to i64 - %N = alloca i32, align 4 - %1 = ptrtoint i32* %N to i64 - %saved_stack = alloca i8*, align 8 - %2 = ptrtoint i8** %saved_stack to i64 - %__vla_expr0 = alloca i64, align 8 - %3 = ptrtoint i64* %__vla_expr0 to i64 - %i = alloca i32, align 4 - %4 = ptrtoint i32* %i to i64 - %w = alloca i64, align 8 - %5 = ptrtoint i64* %w to i64 - %i1 = alloca i32, align 4 - %6 = ptrtoint i32* %i1 to i64 - %7 = ptrtoint i32* %retval to i64 - store i32 0, i32* %retval, align 4 - call void @llvm.dbg.declare(metadata i32* %N, metadata !34, metadata !DIExpression()), !dbg !35 - %8 = ptrtoint i32* %N to i64 - store i32 100000, i32* %N, align 4, !dbg !35 - %9 = ptrtoint i32* %N to i64 - %10 = load i32, i32* %N, align 4, !dbg !36 - %11 = zext i32 %10 to i64, !dbg !37 - call void @__dp_call(i32 16399), !dbg !37 - %12 = call i8* @llvm.stacksave(), !dbg !37 - %13 = ptrtoint i8** %saved_stack to i64 - store i8* %12, i8** %saved_stack, align 8, !dbg !37 - %vla = alloca i32, i64 %11, align 16, !dbg !37 - %14 = ptrtoint i32* %vla to i64, !dbg !37 - %15 = add i64 %14, %11, !dbg !37 - %16 = mul i64 %11, 4, !dbg !37 - call void @__dp_alloca(i32 16399, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.26, i32 0, i32 0), i64 %14, i64 %15, i64 %16, i64 %11), !dbg !37 - %17 = ptrtoint i64* %__vla_expr0 to i64 - store i64 %11, i64* %__vla_expr0, align 8, !dbg !37 - call void @llvm.dbg.declare(metadata i64* %__vla_expr0, metadata !38, metadata !DIExpression()), !dbg !40 - call void @llvm.dbg.declare(metadata i32* %vla, metadata !41, metadata !DIExpression()), !dbg !45 - call void @llvm.dbg.declare(metadata i32* %i, metadata !46, metadata !DIExpression()), !dbg !48 - %18 = ptrtoint i32* %i to i64 - store i32 0, i32* %i, align 4, !dbg !48 - call void @__dp_report_bb(i32 6) - br label %for.cond, !dbg !49 - -for.cond: ; preds = %for.inc, %entry - call void @__dp_loop_entry(i32 16402, i32 0) - %19 = ptrtoint i32* %i to i64 - %20 = load i32, i32* %i, align 4, !dbg !50 - %21 = ptrtoint i32* %N to i64 - %22 = load i32, i32* %N, align 4, !dbg !52 - %cmp = icmp slt i32 %20, %22, !dbg !53 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.6, i32 0, i32 0), i1 %cmp, i32 1), !dbg !54 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.7, i32 0, i32 0), i1 %cmp, i32 0), !dbg !54 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.8, i32 0, i32 0), i1 %cmp, i32 0), !dbg !54 - call void @__dp_report_bb(i32 9) - %23 = load i32, i32* %__dp_bb, align 4 - call void @__dp_report_bb_pair(i32 %23, i32 16) - br i1 %cmp, label %for.body, label %for.end, !dbg !54 - -for.body: ; preds = %for.cond - call void @__dp_loop_incr(i32 2) - %24 = ptrtoint i32* %i to i64 - %25 = load i32, i32* %i, align 4, !dbg !55 - %idxprom = sext i32 %25 to i64, !dbg !57 - %arrayidx = getelementptr inbounds i32, i32* %vla, i64 %idxprom, !dbg !57 - %26 = ptrtoint i32* %arrayidx to i64 - call void @__dp_write(i32 16403, i64 %26, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.26, i32 0, i32 0)) - store i32 0, i32* %arrayidx, align 4, !dbg !58 - call void @__dp_report_bb(i32 7) - %27 = load i32, i32* %__dp_bb, align 4 - call void @__dp_report_bb_pair(i32 %27, i32 15) - br label %for.inc, !dbg !59 - -for.inc: ; preds = %for.body - %28 = ptrtoint i32* %i to i64 - %29 = load i32, i32* %i, align 4, !dbg !60 - %inc = add nsw i32 %29, 1, !dbg !60 - %30 = ptrtoint i32* %i to i64 - store i32 %inc, i32* %i, align 4, !dbg !60 - call void @__dp_report_bb(i32 10) - %31 = load i32, i32* %__dp_bb, align 4 - call void @__dp_report_bb_pair(i32 %31, i32 17) - store i32 1, i32* %__dp_bb, align 4 - br label %for.cond, !dbg !61, !llvm.loop !62 - -for.end: ; preds = %for.cond - call void @__dp_loop_exit(i32 16406, i32 0) - call void @llvm.dbg.declare(metadata i64* %w, metadata !64, metadata !DIExpression()), !dbg !66 - %32 = ptrtoint i64* %w to i64 - store i64 0, i64* %w, align 8, !dbg !66 - call void @llvm.dbg.declare(metadata i32* %i1, metadata !67, metadata !DIExpression()), !dbg !69 - %33 = ptrtoint i32* %i1 to i64 - store i32 0, i32* %i1, align 4, !dbg !69 - call void @__dp_report_bb(i32 8) - br label %for.cond2, !dbg !70 - -for.cond2: ; preds = %for.inc10, %for.end - call void @__dp_loop_entry(i32 16409, i32 1) - %34 = ptrtoint i32* %i1 to i64 - %35 = load i32, i32* %i1, align 4, !dbg !71 - %36 = ptrtoint i32* %N to i64 - %37 = load i32, i32* %N, align 4, !dbg !73 - %cmp3 = icmp slt i32 %35, %37, !dbg !74 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.9, i32 0, i32 0), i1 %cmp3, i32 1), !dbg !75 - call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.10, i32 0, i32 0), i1 %cmp3, i32 0), !dbg !75 - call void @__dp_report_bb(i32 12) - %38 = load i32, i32* %__dp_bb13, align 4 - call void @__dp_report_bb_pair(i32 %38, i32 18) - br i1 %cmp3, label %for.body4, label %for.end12, !dbg !75 - -for.body4: ; preds = %for.cond2 - call void @__dp_loop_incr(i32 1) - %39 = ptrtoint i32* %i1 to i64 - %40 = load i32, i32* %i1, align 4, !dbg !76 - call void @__dp_call(i32 16410), !dbg !78 - %call = call i32 @_Z1gi(i32 %40), !dbg !78 - %idxprom5 = sext i32 %call to i64, !dbg !79 - %arrayidx6 = getelementptr inbounds i32, i32* %vla, i64 %idxprom5, !dbg !79 - %41 = ptrtoint i32* %arrayidx6 to i64 - call void @__dp_read(i32 16410, i64 %41, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.26, i32 0, i32 0)) - %42 = load i32, i32* %arrayidx6, align 4, !dbg !79 - %conv = sext i32 %42 to i64, !dbg !79 - %43 = ptrtoint i64* %w to i64 - %44 = load i64, i64* %w, align 8, !dbg !80 - %add = add nsw i64 %44, %conv, !dbg !80 - %45 = ptrtoint i64* %w to i64 - store i64 %add, i64* %w, align 8, !dbg !80 - %46 = ptrtoint i32* %i1 to i64 - %47 = load i32, i32* %i1, align 4, !dbg !81 - call void @__dp_call(i32 16411), !dbg !82 - %call7 = call i32 @_Z1fi(i32 %47), !dbg !82 - %idxprom8 = sext i32 %call7 to i64, !dbg !83 - %arrayidx9 = getelementptr inbounds i32, i32* %vla, i64 %idxprom8, !dbg !83 - %48 = ptrtoint i32* %arrayidx9 to i64 - call void @__dp_write(i32 16411, i64 %48, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.26, i32 0, i32 0)) - store i32 1, i32* %arrayidx9, align 4, !dbg !84 - call void @__dp_report_bb(i32 14) - %49 = load i32, i32* %__dp_bb13, align 4 - call void @__dp_report_bb_pair(i32 %49, i32 20) - %50 = load i32, i32* %__dp_bb14, align 4 - call void @__dp_report_bb_pair(i32 %50, i32 21) - store i32 1, i32* %__dp_bb14, align 4 - br label %for.inc10, !dbg !85 - -for.inc10: ; preds = %for.body4 - %51 = ptrtoint i32* %i1 to i64 - %52 = load i32, i32* %i1, align 4, !dbg !86 - %inc11 = add nsw i32 %52, 1, !dbg !86 - %53 = ptrtoint i32* %i1 to i64 - store i32 %inc11, i32* %i1, align 4, !dbg !86 - call void @__dp_report_bb(i32 13) - %54 = load i32, i32* %__dp_bb13, align 4 - call void @__dp_report_bb_pair(i32 %54, i32 19) - store i32 1, i32* %__dp_bb13, align 4 - br label %for.cond2, !dbg !87, !llvm.loop !88 - -for.end12: ; preds = %for.cond2 - call void @__dp_loop_exit(i32 16413, i32 1) - %55 = ptrtoint i8** %saved_stack to i64 - %56 = load i8*, i8** %saved_stack, align 8, !dbg !90 - call void @__dp_call(i32 16413), !dbg !90 - call void @llvm.stackrestore(i8* %56), !dbg !90 - %57 = ptrtoint i32* %retval to i64 - %58 = load i32, i32* %retval, align 4, !dbg !90 - call void @__dp_report_bb(i32 11) - call void @__dp_finalize(i32 16413), !dbg !90 - call void @__dp_loop_output(), !dbg !90 - call void @__dp_taken_branch_counter_output(), !dbg !90 - ret i32 %58, !dbg !90 -} - -; Function Attrs: nounwind -declare i8* @llvm.stacksave() #3 - -; Function Attrs: nounwind -declare void @llvm.stackrestore(i8*) #3 - -declare void @__dp_init(i32, i32, i32) - -declare void @__dp_finalize(i32) - -declare void @__dp_read(i32, i64, i8*) - -declare void @__dp_write(i32, i64, i8*) - -declare void @__dp_alloca(i32, i8*, i64, i64, i64, i64) - -declare void @__dp_new(i32, i64, i64, i64) - -declare void @__dp_delete(i32, i64) - -declare void @__dp_call(i32) - -declare void @__dp_func_entry(i32, i32) - -declare void @__dp_func_exit(i32, i32) - -declare void @__dp_loop_entry(i32, i32) - -declare void @__dp_loop_exit(i32, i32) - -declare void @__dp_incr_taken_branch_counter(i8*, i32, i32) - -declare void @__dp_report_bb(i32) - -declare void @__dp_report_bb_pair(i32, i32) - -declare void @__dp_loop_incr(i32) - -declare void @__dp_loop_output() - -declare void @__dp_taken_branch_counter_output() - -attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { nounwind readnone speculatable willreturn } -attributes #2 = { noinline norecurse nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #3 = { nounwind } - -!llvm.dbg.cu = !{!0} -!llvm.module.flags = !{!3, !4, !5, !6} -!llvm.ident = !{!7} - -!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 11.1.0 (https://github.com/llvm/llvm-project.git 7e99bddfeaab2713a8bb6ca538da25b66e6efc59)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None) -!1 = !DIFile(filename: "code.cpp", directory: "/home/lukas/git/discopop/test/end_to_end/reduction_pattern/negative/case_1/src") -!2 = !{} -!3 = !{i32 7, !"Dwarf Version", i32 4} -!4 = !{i32 2, !"Debug Info Version", i32 3} -!5 = !{i32 1, !"wchar_size", i32 4} -!6 = !{i32 7, !"PIC Level", i32 2} -!7 = !{!"clang version 11.1.0 (https://github.com/llvm/llvm-project.git 7e99bddfeaab2713a8bb6ca538da25b66e6efc59)"} -!8 = distinct !DISubprogram(name: "f", linkageName: "_Z1fi", scope: !1, file: !1, line: 3, type: !9, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) -!9 = !DISubroutineType(types: !10) -!10 = !{!11, !11} -!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) -!12 = !DILocalVariable(name: "i", arg: 1, scope: !8, file: !1, line: 3, type: !11) -!13 = !DILocation(line: 3, column: 11, scope: !8) -!14 = !DILocation(line: 4, column: 7, scope: !15) -!15 = distinct !DILexicalBlock(scope: !8, file: !1, line: 4, column: 7) -!16 = !DILocation(line: 4, column: 9, scope: !15) -!17 = !DILocation(line: 4, column: 7, scope: !8) -!18 = !DILocation(line: 5, column: 12, scope: !19) -!19 = distinct !DILexicalBlock(scope: !15, file: !1, line: 4, column: 23) -!20 = !DILocation(line: 5, column: 14, scope: !19) -!21 = !DILocation(line: 5, column: 5, scope: !19) -!22 = !DILocation(line: 7, column: 12, scope: !23) -!23 = distinct !DILexicalBlock(scope: !15, file: !1, line: 6, column: 10) -!24 = !DILocation(line: 7, column: 5, scope: !23) -!25 = !DILocation(line: 9, column: 1, scope: !8) -!26 = distinct !DISubprogram(name: "g", linkageName: "_Z1gi", scope: !1, file: !1, line: 11, type: !9, scopeLine: 11, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) -!27 = !DILocalVariable(name: "i", arg: 1, scope: !26, file: !1, line: 11, type: !11) -!28 = !DILocation(line: 11, column: 11, scope: !26) -!29 = !DILocation(line: 11, column: 23, scope: !26) -!30 = !DILocation(line: 11, column: 16, scope: !26) -!31 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 13, type: !32, scopeLine: 13, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) -!32 = !DISubroutineType(types: !33) -!33 = !{!11} -!34 = !DILocalVariable(name: "N", scope: !31, file: !1, line: 14, type: !11) -!35 = !DILocation(line: 14, column: 7, scope: !31) -!36 = !DILocation(line: 15, column: 11, scope: !31) -!37 = !DILocation(line: 15, column: 3, scope: !31) -!38 = !DILocalVariable(name: "__vla_expr0", scope: !31, type: !39, flags: DIFlagArtificial) -!39 = !DIBasicType(name: "long unsigned int", size: 64, encoding: DW_ATE_unsigned) -!40 = !DILocation(line: 0, scope: !31) -!41 = !DILocalVariable(name: "Arr", scope: !31, file: !1, line: 15, type: !42) -!42 = !DICompositeType(tag: DW_TAG_array_type, baseType: !11, elements: !43) -!43 = !{!44} -!44 = !DISubrange(count: !38) -!45 = !DILocation(line: 15, column: 7, scope: !31) -!46 = !DILocalVariable(name: "i", scope: !47, file: !1, line: 18, type: !11) -!47 = distinct !DILexicalBlock(scope: !31, file: !1, line: 18, column: 3) -!48 = !DILocation(line: 18, column: 12, scope: !47) -!49 = !DILocation(line: 18, column: 8, scope: !47) -!50 = !DILocation(line: 18, column: 19, scope: !51) -!51 = distinct !DILexicalBlock(scope: !47, file: !1, line: 18, column: 3) -!52 = !DILocation(line: 18, column: 23, scope: !51) -!53 = !DILocation(line: 18, column: 21, scope: !51) -!54 = !DILocation(line: 18, column: 3, scope: !47) -!55 = !DILocation(line: 19, column: 9, scope: !56) -!56 = distinct !DILexicalBlock(scope: !51, file: !1, line: 18, column: 31) -!57 = !DILocation(line: 19, column: 5, scope: !56) -!58 = !DILocation(line: 19, column: 12, scope: !56) -!59 = !DILocation(line: 20, column: 3, scope: !56) -!60 = !DILocation(line: 18, column: 27, scope: !51) -!61 = !DILocation(line: 18, column: 3, scope: !51) -!62 = distinct !{!62, !54, !63} -!63 = !DILocation(line: 20, column: 3, scope: !47) -!64 = !DILocalVariable(name: "w", scope: !31, file: !1, line: 22, type: !65) -!65 = !DIBasicType(name: "long int", size: 64, encoding: DW_ATE_signed) -!66 = !DILocation(line: 22, column: 8, scope: !31) -!67 = !DILocalVariable(name: "i", scope: !68, file: !1, line: 25, type: !11) -!68 = distinct !DILexicalBlock(scope: !31, file: !1, line: 25, column: 3) -!69 = !DILocation(line: 25, column: 12, scope: !68) -!70 = !DILocation(line: 25, column: 8, scope: !68) -!71 = !DILocation(line: 25, column: 19, scope: !72) -!72 = distinct !DILexicalBlock(scope: !68, file: !1, line: 25, column: 3) -!73 = !DILocation(line: 25, column: 23, scope: !72) -!74 = !DILocation(line: 25, column: 21, scope: !72) -!75 = !DILocation(line: 25, column: 3, scope: !68) -!76 = !DILocation(line: 26, column: 16, scope: !77) -!77 = distinct !DILexicalBlock(scope: !72, file: !1, line: 25, column: 31) -!78 = !DILocation(line: 26, column: 14, scope: !77) -!79 = !DILocation(line: 26, column: 10, scope: !77) -!80 = !DILocation(line: 26, column: 7, scope: !77) -!81 = !DILocation(line: 27, column: 11, scope: !77) -!82 = !DILocation(line: 27, column: 9, scope: !77) -!83 = !DILocation(line: 27, column: 5, scope: !77) -!84 = !DILocation(line: 27, column: 15, scope: !77) -!85 = !DILocation(line: 28, column: 3, scope: !77) -!86 = !DILocation(line: 25, column: 27, scope: !72) -!87 = !DILocation(line: 25, column: 3, scope: !72) -!88 = distinct !{!88, !75, !89} -!89 = !DILocation(line: 28, column: 3, scope: !68) -!90 = !DILocation(line: 29, column: 1, scope: !31) diff --git a/test/end_to_end/reduction_pattern/positive/nested/OMPSCR/c_Mandelbrot/src/FileMapping.txt b/test/end_to_end/reduction_pattern/positive/nested/OMPSCR/c_Mandelbrot/src/FileMapping.txt deleted file mode 100644 index 46bd31fbb..000000000 --- a/test/end_to_end/reduction_pattern/positive/nested/OMPSCR/c_Mandelbrot/src/FileMapping.txt +++ /dev/null @@ -1 +0,0 @@ -1 /home/lukas/git/discopop/test/end_to_end/reduction_pattern/positive/nested/OMPSCR/c_Mandelbrot/src/code.cpp diff --git a/test/end_to_end/sharing_clauses/__init__.py b/test/end_to_end/sharing_clauses/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/end_to_end/sharing_clauses/do_all/__init__.py b/test/end_to_end/sharing_clauses/do_all/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/end_to_end/sharing_clauses/do_all/first_private/__init__.py b/test/end_to_end/sharing_clauses/do_all/first_private/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/end_to_end/sharing_clauses/do_all/first_private/case_1/__init__.py b/test/end_to_end/sharing_clauses/do_all/first_private/case_1/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/end_to_end/sharing_clauses/do_all/first_private/case_1/src/Makefile b/test/end_to_end/sharing_clauses/do_all/first_private/case_1/src/Makefile new file mode 100644 index 000000000..8b1635880 --- /dev/null +++ b/test/end_to_end/sharing_clauses/do_all/first_private/case_1/src/Makefile @@ -0,0 +1,15 @@ +all: clean prog + +prog: code.o + $(CXX) -o prog code.o $(CXXFLAGS) + +code.o: + $(CXX) -c -o code.o code.cpp $(CXXFLAGS) + +clean: + rm -rf .discopop + rm -rf src/.discopop + find . -not -name code.cpp -not -name Makefile -not -path **/FileMapping.txt -delete + +veryclean: clean + rm -f FileMapping.txt diff --git a/test/end_to_end/sharing_clauses/do_all/first_private/case_1/src/code.cpp b/test/end_to_end/sharing_clauses/do_all/first_private/case_1/src/code.cpp new file mode 100644 index 000000000..d24d1dd62 --- /dev/null +++ b/test/end_to_end/sharing_clauses/do_all/first_private/case_1/src/code.cpp @@ -0,0 +1,14 @@ +#include +#include + +int main(int argc, const char *argv[]) { + static int n = 50000; + int z = 123.456; + + // DO-ALL firstprivate(z) + for (int i = 0; i < n; i++) { + int a = z + i; + z = a + i; + int x = z; + } +} diff --git a/test/end_to_end/sharing_clauses/do_all/first_private/case_1/test.py b/test/end_to_end/sharing_clauses/do_all/first_private/case_1/test.py new file mode 100644 index 000000000..07988dd52 --- /dev/null +++ b/test/end_to_end/sharing_clauses/do_all/first_private/case_1/test.py @@ -0,0 +1,82 @@ +import copy +import os +import pathlib +import subprocess +from typing import Dict, List +import unittest + +import jsonpickle + +from discopop_library.result_classes.DetectionResult import DetectionResult +from test.utils.sharing_clauses.clauses_utils import check_clauses_for_FN, check_clauses_for_FP +from test.utils.subprocess_wrapper.command_execution_wrapper import run_cmd +from test.utils.validator_classes.DoAllInfoForValidation import DoAllInfoForValidation +from subprocess import DEVNULL +from discopop_library.ConfigProvider.config_provider import run as run_config_provider +from discopop_library.ConfigProvider.ConfigProviderArguments import ConfigProviderArguments + + +class TestMethods(unittest.TestCase): + @classmethod + def setUpClass(self): + current_dir = pathlib.Path(__file__).parent.resolve() + dp_build_dir = run_config_provider( + ConfigProviderArguments( + return_dp_build_dir=True, + return_dp_source_dir=False, + return_llvm_bin_dir=False, + return_full_config=False, + return_version_string=False, + ) + ) + + env_vars = dict(os.environ) + + src_dir = os.path.join(current_dir, "src") + # create FileMapping + cmd = os.path.join(dp_build_dir, "scripts", "dp-fmap") + run_cmd(cmd, src_dir, env_vars) + + # build + env_vars["CC"] = os.path.join(dp_build_dir, "scripts", "CC_wrapper.sh") + env_vars["CXX"] = os.path.join(dp_build_dir, "scripts", "CXX_wrapper.sh") + env_vars["DP_PROJECT_ROOT_DIR"] = src_dir + cmd = "make" + run_cmd(cmd, src_dir, env_vars) + + # execute instrumented program + run_cmd("./prog", src_dir, env_vars) + + # execute DiscoPoP analysis + cmd = "discopop_explorer --enable-patterns doall,reduction" + run_cmd(cmd, os.path.join(src_dir, ".discopop"), env_vars) + + self.src_dir = src_dir + self.env_vars = env_vars + + test_output_file = os.path.join(self.src_dir, ".discopop", "explorer", "detection_result_dump.json") + # load detection results + with open(test_output_file, "r") as f: + tmp_str = f.read() + self.test_output: DetectionResult = jsonpickle.decode(tmp_str) + + @classmethod + def tearDownClass(self): + run_cmd("make veryclean", self.src_dir, self.env_vars) + + def test(self): + self.assertIn("do_all", self.test_output.patterns.__dict__) + doall_patterns = self.test_output.patterns.__dict__["do_all"] + self.assertEqual(len(doall_patterns), 1) + do_all_pattern = doall_patterns[0] + + expected_clauses: Dict[str, List[str]] = {"first_private": ["z"]} + + with self.subTest("check pattern for FP data sharing clauses"): + res, msg = check_clauses_for_FP(self, expected_clauses, do_all_pattern) + self.assertTrue(res, msg) + with self.subTest("check pattern for FN data sharing clauses"): + res, msg = check_clauses_for_FN(self, expected_clauses, do_all_pattern) + self.assertTrue(res, msg) + + diff --git a/test/end_to_end/sharing_clauses/do_all/last_private/__init__.py b/test/end_to_end/sharing_clauses/do_all/last_private/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/end_to_end/sharing_clauses/do_all/last_private/case_1/__init__.py b/test/end_to_end/sharing_clauses/do_all/last_private/case_1/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/end_to_end/sharing_clauses/do_all/last_private/case_1/src/Makefile b/test/end_to_end/sharing_clauses/do_all/last_private/case_1/src/Makefile new file mode 100644 index 000000000..8b1635880 --- /dev/null +++ b/test/end_to_end/sharing_clauses/do_all/last_private/case_1/src/Makefile @@ -0,0 +1,15 @@ +all: clean prog + +prog: code.o + $(CXX) -o prog code.o $(CXXFLAGS) + +code.o: + $(CXX) -c -o code.o code.cpp $(CXXFLAGS) + +clean: + rm -rf .discopop + rm -rf src/.discopop + find . -not -name code.cpp -not -name Makefile -not -path **/FileMapping.txt -delete + +veryclean: clean + rm -f FileMapping.txt diff --git a/test/end_to_end/sharing_clauses/do_all/last_private/case_1/src/code.cpp b/test/end_to_end/sharing_clauses/do_all/last_private/case_1/src/code.cpp new file mode 100644 index 000000000..7ad085bc6 --- /dev/null +++ b/test/end_to_end/sharing_clauses/do_all/last_private/case_1/src/code.cpp @@ -0,0 +1,14 @@ +#include +#include + +int main(int argc, const char *argv[]) { + static int n = 50000; + int z = 123.456; + + // DO-ALL lastprivate(z) + for (int i = 0; i < n; i++) { + z = i; + } + + int x = z; +} diff --git a/test/end_to_end/sharing_clauses/do_all/last_private/case_1/test.py b/test/end_to_end/sharing_clauses/do_all/last_private/case_1/test.py new file mode 100644 index 000000000..3aa27443b --- /dev/null +++ b/test/end_to_end/sharing_clauses/do_all/last_private/case_1/test.py @@ -0,0 +1,82 @@ +import copy +import os +import pathlib +import subprocess +from typing import Dict, List +import unittest + +import jsonpickle + +from discopop_library.result_classes.DetectionResult import DetectionResult +from test.utils.sharing_clauses.clauses_utils import check_clauses_for_FN, check_clauses_for_FP +from test.utils.subprocess_wrapper.command_execution_wrapper import run_cmd +from test.utils.validator_classes.DoAllInfoForValidation import DoAllInfoForValidation +from subprocess import DEVNULL +from discopop_library.ConfigProvider.config_provider import run as run_config_provider +from discopop_library.ConfigProvider.ConfigProviderArguments import ConfigProviderArguments + + +class TestMethods(unittest.TestCase): + @classmethod + def setUpClass(self): + current_dir = pathlib.Path(__file__).parent.resolve() + dp_build_dir = run_config_provider( + ConfigProviderArguments( + return_dp_build_dir=True, + return_dp_source_dir=False, + return_llvm_bin_dir=False, + return_full_config=False, + return_version_string=False, + ) + ) + + env_vars = dict(os.environ) + + src_dir = os.path.join(current_dir, "src") + # create FileMapping + cmd = os.path.join(dp_build_dir, "scripts", "dp-fmap") + run_cmd(cmd, src_dir, env_vars) + + # build + env_vars["CC"] = os.path.join(dp_build_dir, "scripts", "CC_wrapper.sh") + env_vars["CXX"] = os.path.join(dp_build_dir, "scripts", "CXX_wrapper.sh") + env_vars["DP_PROJECT_ROOT_DIR"] = src_dir + cmd = "make" + run_cmd(cmd, src_dir, env_vars) + + # execute instrumented program + run_cmd("./prog", src_dir, env_vars) + + # execute DiscoPoP analysis + cmd = "discopop_explorer --enable-patterns doall,reduction" + run_cmd(cmd, os.path.join(src_dir, ".discopop"), env_vars) + + self.src_dir = src_dir + self.env_vars = env_vars + + test_output_file = os.path.join(self.src_dir, ".discopop", "explorer", "detection_result_dump.json") + # load detection results + with open(test_output_file, "r") as f: + tmp_str = f.read() + self.test_output: DetectionResult = jsonpickle.decode(tmp_str) + + @classmethod + def tearDownClass(self): + run_cmd("make veryclean", self.src_dir, self.env_vars) + + def test(self): + self.assertIn("do_all", self.test_output.patterns.__dict__) + doall_patterns = self.test_output.patterns.__dict__["do_all"] + self.assertEqual(len(doall_patterns), 1) + do_all_pattern = doall_patterns[0] + + expected_clauses: Dict[str, List[str]] = {"last_private": ["z"]} + + with self.subTest("check pattern for FP data sharing clauses"): + res, msg = check_clauses_for_FP(self, expected_clauses, do_all_pattern) + self.assertTrue(res, msg) + with self.subTest("check pattern for FN data sharing clauses"): + res, msg = check_clauses_for_FN(self, expected_clauses, do_all_pattern) + self.assertTrue(res, msg) + + diff --git a/test/end_to_end/sharing_clauses/do_all/no_clause/__init__.py b/test/end_to_end/sharing_clauses/do_all/no_clause/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/end_to_end/sharing_clauses/do_all/no_clause/case_1/__init__.py b/test/end_to_end/sharing_clauses/do_all/no_clause/case_1/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/end_to_end/sharing_clauses/do_all/no_clause/case_1/src/Makefile b/test/end_to_end/sharing_clauses/do_all/no_clause/case_1/src/Makefile new file mode 100644 index 000000000..4bc2f0c44 --- /dev/null +++ b/test/end_to_end/sharing_clauses/do_all/no_clause/case_1/src/Makefile @@ -0,0 +1,17 @@ +all: clean prog + +prog: code.o + $(CXX) -o prog code.o $(CXXFLAGS) + +code.o: + $(CXX) -c -S -emit-llvm -o code.ll code.cpp $(CXXFLAGS) + rm -r .discopop + $(CXX) -c -o code.o code.cpp $(CXXFLAGS) + +clean: + rm -rf .discopop + rm -rf src/.discopop + find . -not -name code.cpp -not -name Makefile -not -path **/FileMapping.txt -delete + +veryclean: clean + rm -f FileMapping.txt diff --git a/test/end_to_end/sharing_clauses/do_all/no_clause/case_1/src/code.cpp b/test/end_to_end/sharing_clauses/do_all/no_clause/case_1/src/code.cpp new file mode 100644 index 000000000..61047971c --- /dev/null +++ b/test/end_to_end/sharing_clauses/do_all/no_clause/case_1/src/code.cpp @@ -0,0 +1,11 @@ +#include +#include + +int main(int argc, const char *argv[]) { + static int n = 50000; + + // DO-ALL + for (int i = 0; i < n; i++) { + int x = i; + } +} diff --git a/test/end_to_end/sharing_clauses/do_all/no_clause/case_1/test.py b/test/end_to_end/sharing_clauses/do_all/no_clause/case_1/test.py new file mode 100644 index 000000000..a20ac28e5 --- /dev/null +++ b/test/end_to_end/sharing_clauses/do_all/no_clause/case_1/test.py @@ -0,0 +1,82 @@ +import copy +import os +import pathlib +import subprocess +from typing import Dict, List +import unittest + +import jsonpickle + +from discopop_library.result_classes.DetectionResult import DetectionResult +from test.utils.sharing_clauses.clauses_utils import check_clauses_for_FN, check_clauses_for_FP +from test.utils.subprocess_wrapper.command_execution_wrapper import run_cmd +from test.utils.validator_classes.DoAllInfoForValidation import DoAllInfoForValidation +from subprocess import DEVNULL +from discopop_library.ConfigProvider.config_provider import run as run_config_provider +from discopop_library.ConfigProvider.ConfigProviderArguments import ConfigProviderArguments + + +class TestMethods(unittest.TestCase): + @classmethod + def setUpClass(self): + current_dir = pathlib.Path(__file__).parent.resolve() + dp_build_dir = run_config_provider( + ConfigProviderArguments( + return_dp_build_dir=True, + return_dp_source_dir=False, + return_llvm_bin_dir=False, + return_full_config=False, + return_version_string=False, + ) + ) + + env_vars = dict(os.environ) + + src_dir = os.path.join(current_dir, "src") + # create FileMapping + cmd = os.path.join(dp_build_dir, "scripts", "dp-fmap") + run_cmd(cmd, src_dir, env_vars) + + # build + env_vars["CC"] = os.path.join(dp_build_dir, "scripts", "CC_wrapper.sh") + env_vars["CXX"] = os.path.join(dp_build_dir, "scripts", "CXX_wrapper.sh") + env_vars["DP_PROJECT_ROOT_DIR"] = src_dir + cmd = "make" + run_cmd(cmd, src_dir, env_vars) + + # execute instrumented program + run_cmd("./prog", src_dir, env_vars) + + # execute DiscoPoP analysis + cmd = "discopop_explorer --enable-patterns doall,reduction" + run_cmd(cmd, os.path.join(src_dir, ".discopop"), env_vars) + + self.src_dir = src_dir + self.env_vars = env_vars + + test_output_file = os.path.join(self.src_dir, ".discopop", "explorer", "detection_result_dump.json") + # load detection results + with open(test_output_file, "r") as f: + tmp_str = f.read() + self.test_output: DetectionResult = jsonpickle.decode(tmp_str) + + @classmethod + def tearDownClass(self): + run_cmd("make veryclean", self.src_dir, self.env_vars) + + def test(self): + self.assertIn("do_all", self.test_output.patterns.__dict__) + doall_patterns = self.test_output.patterns.__dict__["do_all"] + self.assertEqual(len(doall_patterns), 1) + do_all_pattern = doall_patterns[0] + + expected_clauses: Dict[str, List[str]] = {} + + with self.subTest("check pattern for FP data sharing clauses"): + res, msg = check_clauses_for_FP(self, expected_clauses, do_all_pattern) + self.assertTrue(res, msg) + with self.subTest("check pattern for FN data sharing clauses"): + res, msg = check_clauses_for_FN(self, expected_clauses, do_all_pattern) + self.assertTrue(res, msg) + + diff --git a/test/end_to_end/sharing_clauses/do_all/private/__init__.py b/test/end_to_end/sharing_clauses/do_all/private/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/end_to_end/sharing_clauses/do_all/private/case_1/__init__.py b/test/end_to_end/sharing_clauses/do_all/private/case_1/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/end_to_end/sharing_clauses/do_all/private/case_1/src/Makefile b/test/end_to_end/sharing_clauses/do_all/private/case_1/src/Makefile new file mode 100644 index 000000000..8b1635880 --- /dev/null +++ b/test/end_to_end/sharing_clauses/do_all/private/case_1/src/Makefile @@ -0,0 +1,15 @@ +all: clean prog + +prog: code.o + $(CXX) -o prog code.o $(CXXFLAGS) + +code.o: + $(CXX) -c -o code.o code.cpp $(CXXFLAGS) + +clean: + rm -rf .discopop + rm -rf src/.discopop + find . -not -name code.cpp -not -name Makefile -not -path **/FileMapping.txt -delete + +veryclean: clean + rm -f FileMapping.txt diff --git a/test/end_to_end/sharing_clauses/do_all/private/case_1/src/code.cpp b/test/end_to_end/sharing_clauses/do_all/private/case_1/src/code.cpp new file mode 100644 index 000000000..e3338a20b --- /dev/null +++ b/test/end_to_end/sharing_clauses/do_all/private/case_1/src/code.cpp @@ -0,0 +1,15 @@ +#include +#include + +int main(int argc, const char *argv[]) { + static int n = 50000; + + int y = 42; + int z = 0; + + // DO-ALL shared(y) private(z) + for (int i = 0; i < n; i++) { + z = y + i; + int x = z; + } +} diff --git a/test/end_to_end/sharing_clauses/do_all/private/case_1/test.py b/test/end_to_end/sharing_clauses/do_all/private/case_1/test.py new file mode 100644 index 000000000..85e40a9cb --- /dev/null +++ b/test/end_to_end/sharing_clauses/do_all/private/case_1/test.py @@ -0,0 +1,82 @@ +import copy +import os +import pathlib +import subprocess +from typing import Dict, List +import unittest + +import jsonpickle + +from discopop_library.result_classes.DetectionResult import DetectionResult +from test.utils.sharing_clauses.clauses_utils import check_clauses_for_FN, check_clauses_for_FP +from test.utils.subprocess_wrapper.command_execution_wrapper import run_cmd +from test.utils.validator_classes.DoAllInfoForValidation import DoAllInfoForValidation +from subprocess import DEVNULL +from discopop_library.ConfigProvider.config_provider import run as run_config_provider +from discopop_library.ConfigProvider.ConfigProviderArguments import ConfigProviderArguments + + +class TestMethods(unittest.TestCase): + @classmethod + def setUpClass(self): + current_dir = pathlib.Path(__file__).parent.resolve() + dp_build_dir = run_config_provider( + ConfigProviderArguments( + return_dp_build_dir=True, + return_dp_source_dir=False, + return_llvm_bin_dir=False, + return_full_config=False, + return_version_string=False, + ) + ) + + env_vars = dict(os.environ) + + src_dir = os.path.join(current_dir, "src") + # create FileMapping + cmd = os.path.join(dp_build_dir, "scripts", "dp-fmap") + run_cmd(cmd, src_dir, env_vars) + + # build + env_vars["CC"] = os.path.join(dp_build_dir, "scripts", "CC_wrapper.sh") + env_vars["CXX"] = os.path.join(dp_build_dir, "scripts", "CXX_wrapper.sh") + env_vars["DP_PROJECT_ROOT_DIR"] = src_dir + cmd = "make" + run_cmd(cmd, src_dir, env_vars) + + # execute instrumented program + run_cmd("./prog", src_dir, env_vars) + + # execute DiscoPoP analysis + cmd = "discopop_explorer --enable-patterns doall,reduction" + run_cmd(cmd, os.path.join(src_dir, ".discopop"), env_vars) + + self.src_dir = src_dir + self.env_vars = env_vars + + test_output_file = os.path.join(self.src_dir, ".discopop", "explorer", "detection_result_dump.json") + # load detection results + with open(test_output_file, "r") as f: + tmp_str = f.read() + self.test_output: DetectionResult = jsonpickle.decode(tmp_str) + + @classmethod + def tearDownClass(self): + run_cmd("make veryclean", self.src_dir, self.env_vars) + + def test(self): + self.assertIn("do_all", self.test_output.patterns.__dict__) + doall_patterns = self.test_output.patterns.__dict__["do_all"] + self.assertEqual(len(doall_patterns), 1) + do_all_pattern = doall_patterns[0] + + expected_clauses: Dict[str, List[str]] = {"shared": ["y"], "private": ["z"]} + + with self.subTest("check pattern for FP data sharing clauses"): + res, msg = check_clauses_for_FP(self, expected_clauses, do_all_pattern) + self.assertTrue(res, msg) + with self.subTest("check pattern for FN data sharing clauses"): + res, msg = check_clauses_for_FN(self, expected_clauses, do_all_pattern) + self.assertTrue(res, msg) + + diff --git a/test/end_to_end/sharing_clauses/do_all/shared/__init__.py b/test/end_to_end/sharing_clauses/do_all/shared/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/end_to_end/sharing_clauses/do_all/shared/case_1/__init__.py b/test/end_to_end/sharing_clauses/do_all/shared/case_1/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/end_to_end/sharing_clauses/do_all/shared/case_1/src/Makefile b/test/end_to_end/sharing_clauses/do_all/shared/case_1/src/Makefile new file mode 100644 index 000000000..8b1635880 --- /dev/null +++ b/test/end_to_end/sharing_clauses/do_all/shared/case_1/src/Makefile @@ -0,0 +1,15 @@ +all: clean prog + +prog: code.o + $(CXX) -o prog code.o $(CXXFLAGS) + +code.o: + $(CXX) -c -o code.o code.cpp $(CXXFLAGS) + +clean: + rm -rf .discopop + rm -rf src/.discopop + find . -not -name code.cpp -not -name Makefile -not -path **/FileMapping.txt -delete + +veryclean: clean + rm -f FileMapping.txt diff --git a/test/end_to_end/sharing_clauses/do_all/shared/case_1/src/code.cpp b/test/end_to_end/sharing_clauses/do_all/shared/case_1/src/code.cpp new file mode 100644 index 000000000..3a6d6b879 --- /dev/null +++ b/test/end_to_end/sharing_clauses/do_all/shared/case_1/src/code.cpp @@ -0,0 +1,17 @@ +#include +#include + +int main(int argc, const char *argv[]) { + static int n = 50000; + + double *Arr = (double *) malloc(n*sizeof(double)); + Arr[42] = 123.456; + + int z = 0; + + // DO-ALL shared(Arr) private(z) + for (int i = 0; i < n; i++) { + z = Arr[42] + i; + int x = z; + } +} diff --git a/test/end_to_end/sharing_clauses/do_all/shared/case_1/test.py b/test/end_to_end/sharing_clauses/do_all/shared/case_1/test.py new file mode 100644 index 000000000..56a127e69 --- /dev/null +++ b/test/end_to_end/sharing_clauses/do_all/shared/case_1/test.py @@ -0,0 +1,82 @@ +import copy +import os +import pathlib +import subprocess +from typing import Dict, List +import unittest + +import jsonpickle + +from discopop_library.result_classes.DetectionResult import DetectionResult +from test.utils.sharing_clauses.clauses_utils import check_clauses_for_FN, check_clauses_for_FP +from test.utils.subprocess_wrapper.command_execution_wrapper import run_cmd +from test.utils.validator_classes.DoAllInfoForValidation import DoAllInfoForValidation +from subprocess import DEVNULL +from discopop_library.ConfigProvider.config_provider import run as run_config_provider +from discopop_library.ConfigProvider.ConfigProviderArguments import ConfigProviderArguments + + +class TestMethods(unittest.TestCase): + @classmethod + def setUpClass(self): + current_dir = pathlib.Path(__file__).parent.resolve() + dp_build_dir = run_config_provider( + ConfigProviderArguments( + return_dp_build_dir=True, + return_dp_source_dir=False, + return_llvm_bin_dir=False, + return_full_config=False, + return_version_string=False, + ) + ) + + env_vars = dict(os.environ) + + src_dir = os.path.join(current_dir, "src") + # create FileMapping + cmd = os.path.join(dp_build_dir, "scripts", "dp-fmap") + run_cmd(cmd, src_dir, env_vars) + + # build + env_vars["CC"] = os.path.join(dp_build_dir, "scripts", "CC_wrapper.sh") + env_vars["CXX"] = os.path.join(dp_build_dir, "scripts", "CXX_wrapper.sh") + env_vars["DP_PROJECT_ROOT_DIR"] = src_dir + cmd = "make" + run_cmd(cmd, src_dir, env_vars) + + # execute instrumented program + run_cmd("./prog", src_dir, env_vars) + + # execute DiscoPoP analysis + cmd = "discopop_explorer --enable-patterns doall,reduction" + run_cmd(cmd, os.path.join(src_dir, ".discopop"), env_vars) + + self.src_dir = src_dir + self.env_vars = env_vars + + test_output_file = os.path.join(self.src_dir, ".discopop", "explorer", "detection_result_dump.json") + # load detection results + with open(test_output_file, "r") as f: + tmp_str = f.read() + self.test_output: DetectionResult = jsonpickle.decode(tmp_str) + + @classmethod + def tearDownClass(self): + run_cmd("make veryclean", self.src_dir, self.env_vars) + + def test(self): + self.assertIn("do_all", self.test_output.patterns.__dict__) + doall_patterns = self.test_output.patterns.__dict__["do_all"] + self.assertEqual(len(doall_patterns), 1) + do_all_pattern = doall_patterns[0] + + expected_clauses: Dict[str, List[str]] = {"shared": ["Arr"], "private": ["z"]} + + with self.subTest("check pattern for FP data sharing clauses"): + res, msg = check_clauses_for_FP(self, expected_clauses, do_all_pattern) + self.assertTrue(res, msg) + with self.subTest("check pattern for FN data sharing clauses"): + res, msg = check_clauses_for_FN(self, expected_clauses, do_all_pattern) + self.assertTrue(res, msg) + + diff --git a/test/end_to_end/sharing_clauses/do_all/shared/case_2/__init__.py b/test/end_to_end/sharing_clauses/do_all/shared/case_2/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/end_to_end/sharing_clauses/do_all/shared/case_2/src/Makefile b/test/end_to_end/sharing_clauses/do_all/shared/case_2/src/Makefile new file mode 100644 index 000000000..8b1635880 --- /dev/null +++ b/test/end_to_end/sharing_clauses/do_all/shared/case_2/src/Makefile @@ -0,0 +1,15 @@ +all: clean prog + +prog: code.o + $(CXX) -o prog code.o $(CXXFLAGS) + +code.o: + $(CXX) -c -o code.o code.cpp $(CXXFLAGS) + +clean: + rm -rf .discopop + rm -rf src/.discopop + find . -not -name code.cpp -not -name Makefile -not -path **/FileMapping.txt -delete + +veryclean: clean + rm -f FileMapping.txt diff --git a/test/end_to_end/sharing_clauses/do_all/shared/case_2/src/code.cpp b/test/end_to_end/sharing_clauses/do_all/shared/case_2/src/code.cpp new file mode 100644 index 000000000..273811504 --- /dev/null +++ b/test/end_to_end/sharing_clauses/do_all/shared/case_2/src/code.cpp @@ -0,0 +1,16 @@ +#include +#include + +int main(int argc, const char *argv[]) { + static int n = 50000; + + double *Arr = (double *) malloc(n*sizeof(double)); + + int z = 0; + + // DO-ALL shared(Arr) + for (int i = 0; i < n; i++) { + Arr[i] = i; + int x = Arr[i]; + } +} diff --git a/test/end_to_end/sharing_clauses/do_all/shared/case_2/test.py b/test/end_to_end/sharing_clauses/do_all/shared/case_2/test.py new file mode 100644 index 000000000..7cbd913ff --- /dev/null +++ b/test/end_to_end/sharing_clauses/do_all/shared/case_2/test.py @@ -0,0 +1,82 @@ +import copy +import os +import pathlib +import subprocess +from typing import Dict, List +import unittest + +import jsonpickle + +from discopop_library.result_classes.DetectionResult import DetectionResult +from test.utils.sharing_clauses.clauses_utils import check_clauses_for_FN, check_clauses_for_FP +from test.utils.subprocess_wrapper.command_execution_wrapper import run_cmd +from test.utils.validator_classes.DoAllInfoForValidation import DoAllInfoForValidation +from subprocess import DEVNULL +from discopop_library.ConfigProvider.config_provider import run as run_config_provider +from discopop_library.ConfigProvider.ConfigProviderArguments import ConfigProviderArguments + + +class TestMethods(unittest.TestCase): + @classmethod + def setUpClass(self): + current_dir = pathlib.Path(__file__).parent.resolve() + dp_build_dir = run_config_provider( + ConfigProviderArguments( + return_dp_build_dir=True, + return_dp_source_dir=False, + return_llvm_bin_dir=False, + return_full_config=False, + return_version_string=False, + ) + ) + + env_vars = dict(os.environ) + + src_dir = os.path.join(current_dir, "src") + # create FileMapping + cmd = os.path.join(dp_build_dir, "scripts", "dp-fmap") + run_cmd(cmd, src_dir, env_vars) + + # build + env_vars["CC"] = os.path.join(dp_build_dir, "scripts", "CC_wrapper.sh") + env_vars["CXX"] = os.path.join(dp_build_dir, "scripts", "CXX_wrapper.sh") + env_vars["DP_PROJECT_ROOT_DIR"] = src_dir + cmd = "make" + run_cmd(cmd, src_dir, env_vars) + + # execute instrumented program + run_cmd("./prog", src_dir, env_vars) + + # execute DiscoPoP analysis + cmd = "discopop_explorer --enable-patterns doall,reduction" + run_cmd(cmd, os.path.join(src_dir, ".discopop"), env_vars) + + self.src_dir = src_dir + self.env_vars = env_vars + + test_output_file = os.path.join(self.src_dir, ".discopop", "explorer", "detection_result_dump.json") + # load detection results + with open(test_output_file, "r") as f: + tmp_str = f.read() + self.test_output: DetectionResult = jsonpickle.decode(tmp_str) + + @classmethod + def tearDownClass(self): + run_cmd("make veryclean", self.src_dir, self.env_vars) + + def test(self): + self.assertIn("do_all", self.test_output.patterns.__dict__) + doall_patterns = self.test_output.patterns.__dict__["do_all"] + self.assertEqual(len(doall_patterns), 1) + do_all_pattern = doall_patterns[0] + + expected_clauses: Dict[str, List[str]] = {"shared": ["Arr"]} + + with self.subTest("check pattern for FP data sharing clauses"): + res, msg = check_clauses_for_FP(self, expected_clauses, do_all_pattern) + self.assertTrue(res, msg) + with self.subTest("check pattern for FN data sharing clauses"): + res, msg = check_clauses_for_FN(self, expected_clauses, do_all_pattern) + self.assertTrue(res, msg) + + diff --git a/test/end_to_end/sharing_clauses/do_all/shared/case_3/__init__.py b/test/end_to_end/sharing_clauses/do_all/shared/case_3/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/end_to_end/sharing_clauses/do_all/shared/case_3/src/Makefile b/test/end_to_end/sharing_clauses/do_all/shared/case_3/src/Makefile new file mode 100644 index 000000000..8b1635880 --- /dev/null +++ b/test/end_to_end/sharing_clauses/do_all/shared/case_3/src/Makefile @@ -0,0 +1,15 @@ +all: clean prog + +prog: code.o + $(CXX) -o prog code.o $(CXXFLAGS) + +code.o: + $(CXX) -c -o code.o code.cpp $(CXXFLAGS) + +clean: + rm -rf .discopop + rm -rf src/.discopop + find . -not -name code.cpp -not -name Makefile -not -path **/FileMapping.txt -delete + +veryclean: clean + rm -f FileMapping.txt diff --git a/test/end_to_end/sharing_clauses/do_all/shared/case_3/src/code.cpp b/test/end_to_end/sharing_clauses/do_all/shared/case_3/src/code.cpp new file mode 100644 index 000000000..ef467a627 --- /dev/null +++ b/test/end_to_end/sharing_clauses/do_all/shared/case_3/src/code.cpp @@ -0,0 +1,16 @@ +#include +#include + +int main(int argc, const char *argv[]) { + static int n = 50000; + + double *Arr = (double *) malloc(n*sizeof(double)); + Arr[0] = 1; + Arr[1] = 2; + Arr[2] = 3; + + // DO-ALL shared(Arr) + for (int i = 0; i < n; i++) { + int x = Arr[0] + Arr[1] + Arr[2]; + } +} diff --git a/test/end_to_end/sharing_clauses/do_all/shared/case_3/test.py b/test/end_to_end/sharing_clauses/do_all/shared/case_3/test.py new file mode 100644 index 000000000..7cbd913ff --- /dev/null +++ b/test/end_to_end/sharing_clauses/do_all/shared/case_3/test.py @@ -0,0 +1,82 @@ +import copy +import os +import pathlib +import subprocess +from typing import Dict, List +import unittest + +import jsonpickle + +from discopop_library.result_classes.DetectionResult import DetectionResult +from test.utils.sharing_clauses.clauses_utils import check_clauses_for_FN, check_clauses_for_FP +from test.utils.subprocess_wrapper.command_execution_wrapper import run_cmd +from test.utils.validator_classes.DoAllInfoForValidation import DoAllInfoForValidation +from subprocess import DEVNULL +from discopop_library.ConfigProvider.config_provider import run as run_config_provider +from discopop_library.ConfigProvider.ConfigProviderArguments import ConfigProviderArguments + + +class TestMethods(unittest.TestCase): + @classmethod + def setUpClass(self): + current_dir = pathlib.Path(__file__).parent.resolve() + dp_build_dir = run_config_provider( + ConfigProviderArguments( + return_dp_build_dir=True, + return_dp_source_dir=False, + return_llvm_bin_dir=False, + return_full_config=False, + return_version_string=False, + ) + ) + + env_vars = dict(os.environ) + + src_dir = os.path.join(current_dir, "src") + # create FileMapping + cmd = os.path.join(dp_build_dir, "scripts", "dp-fmap") + run_cmd(cmd, src_dir, env_vars) + + # build + env_vars["CC"] = os.path.join(dp_build_dir, "scripts", "CC_wrapper.sh") + env_vars["CXX"] = os.path.join(dp_build_dir, "scripts", "CXX_wrapper.sh") + env_vars["DP_PROJECT_ROOT_DIR"] = src_dir + cmd = "make" + run_cmd(cmd, src_dir, env_vars) + + # execute instrumented program + run_cmd("./prog", src_dir, env_vars) + + # execute DiscoPoP analysis + cmd = "discopop_explorer --enable-patterns doall,reduction" + run_cmd(cmd, os.path.join(src_dir, ".discopop"), env_vars) + + self.src_dir = src_dir + self.env_vars = env_vars + + test_output_file = os.path.join(self.src_dir, ".discopop", "explorer", "detection_result_dump.json") + # load detection results + with open(test_output_file, "r") as f: + tmp_str = f.read() + self.test_output: DetectionResult = jsonpickle.decode(tmp_str) + + @classmethod + def tearDownClass(self): + run_cmd("make veryclean", self.src_dir, self.env_vars) + + def test(self): + self.assertIn("do_all", self.test_output.patterns.__dict__) + doall_patterns = self.test_output.patterns.__dict__["do_all"] + self.assertEqual(len(doall_patterns), 1) + do_all_pattern = doall_patterns[0] + + expected_clauses: Dict[str, List[str]] = {"shared": ["Arr"]} + + with self.subTest("check pattern for FP data sharing clauses"): + res, msg = check_clauses_for_FP(self, expected_clauses, do_all_pattern) + self.assertTrue(res, msg) + with self.subTest("check pattern for FN data sharing clauses"): + res, msg = check_clauses_for_FN(self, expected_clauses, do_all_pattern) + self.assertTrue(res, msg) + + diff --git a/test/utils/sharing_clauses/__init__.py b/test/utils/sharing_clauses/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/utils/sharing_clauses/clauses_utils.py b/test/utils/sharing_clauses/clauses_utils.py new file mode 100644 index 000000000..983239e54 --- /dev/null +++ b/test/utils/sharing_clauses/clauses_utils.py @@ -0,0 +1,42 @@ + +from typing import Any, Dict, List, Tuple + + +def check_clauses_for_FP(test_cls: Any, expected_clauses: Dict[str, List[str]], pattern: Any) -> Tuple[bool, str]: + """check that only expected clauses are found""" + msg = "" + res = True + unexpected_clauses = "" + for clause_type in ["private", "shared", "first_private", "last_private"]: + for clause_var in pattern.__dict__[clause_type]: + unexpected = False + if clause_type not in expected_clauses: + unexpected = True + elif clause_var.name not in expected_clauses[clause_type]: + unexpected = True + if unexpected: + unexpected_clauses += clause_type + "(" + clause_var.name + ") " + if len(unexpected_clauses) > 0: + msg = "Found unexpected clauses: " + unexpected_clauses + res = False + + return res, msg + +def check_clauses_for_FN(test_cls: Any, expected_clauses: Dict[str, List[str]], pattern: Any) -> Tuple[bool, str]: + """check that all expected clauses are found""" + msg = "" + res = True + missed_clauses = "" + for clause_type in expected_clauses: + for clause_var_name in expected_clauses[clause_type]: + found = False + for found_var in pattern.__dict__[clause_type]: + if found_var.name == clause_var_name: + found = True + break + if not found: + missed_clauses += clause_type + "(" + clause_var_name + ") " + if len(missed_clauses) > 0: + msg = "Missed expected clauses: " + missed_clauses + res = False + return res, msg diff --git a/test/wip_end_to_end/sharing_clauses/__init__.py b/test/wip_end_to_end/sharing_clauses/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/wip_end_to_end/sharing_clauses/do_all/__init__.py b/test/wip_end_to_end/sharing_clauses/do_all/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/wip_end_to_end/sharing_clauses/do_all/first_private/__init__.py b/test/wip_end_to_end/sharing_clauses/do_all/first_private/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/wip_end_to_end/sharing_clauses/do_all/first_private/case_2/__init__.py b/test/wip_end_to_end/sharing_clauses/do_all/first_private/case_2/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/wip_end_to_end/sharing_clauses/do_all/first_private/case_2/src/Makefile b/test/wip_end_to_end/sharing_clauses/do_all/first_private/case_2/src/Makefile new file mode 100644 index 000000000..8b1635880 --- /dev/null +++ b/test/wip_end_to_end/sharing_clauses/do_all/first_private/case_2/src/Makefile @@ -0,0 +1,15 @@ +all: clean prog + +prog: code.o + $(CXX) -o prog code.o $(CXXFLAGS) + +code.o: + $(CXX) -c -o code.o code.cpp $(CXXFLAGS) + +clean: + rm -rf .discopop + rm -rf src/.discopop + find . -not -name code.cpp -not -name Makefile -not -path **/FileMapping.txt -delete + +veryclean: clean + rm -f FileMapping.txt diff --git a/test/wip_end_to_end/sharing_clauses/do_all/first_private/case_2/src/code.cpp b/test/wip_end_to_end/sharing_clauses/do_all/first_private/case_2/src/code.cpp new file mode 100644 index 000000000..5b0d5e510 --- /dev/null +++ b/test/wip_end_to_end/sharing_clauses/do_all/first_private/case_2/src/code.cpp @@ -0,0 +1,16 @@ +#include +#include + +int main(int argc, const char *argv[]) { + static int n = 50000; + + double *Arr = (double *) malloc(n*sizeof(double)); + + // DO-ALL firstprivate(Arr) + for (int i = 0; i < n; i++) { + Arr[0] = Arr[2]; + Arr[1] = Arr[0]; + Arr[2] = Arr[1]; + int x = Arr[0] + Arr[1] + Arr[2]; + } +} diff --git a/test/wip_end_to_end/sharing_clauses/do_all/first_private/case_2/test.py b/test/wip_end_to_end/sharing_clauses/do_all/first_private/case_2/test.py new file mode 100644 index 000000000..671777c0a --- /dev/null +++ b/test/wip_end_to_end/sharing_clauses/do_all/first_private/case_2/test.py @@ -0,0 +1,82 @@ +import copy +import os +import pathlib +import subprocess +from typing import Dict, List +import unittest + +import jsonpickle + +from discopop_library.result_classes.DetectionResult import DetectionResult +from test.utils.sharing_clauses.clauses_utils import check_clauses_for_FN, check_clauses_for_FP +from test.utils.subprocess_wrapper.command_execution_wrapper import run_cmd +from test.utils.validator_classes.DoAllInfoForValidation import DoAllInfoForValidation +from subprocess import DEVNULL +from discopop_library.ConfigProvider.config_provider import run as run_config_provider +from discopop_library.ConfigProvider.ConfigProviderArguments import ConfigProviderArguments + + +class TestMethods(unittest.TestCase): + @classmethod + def setUpClass(self): + current_dir = pathlib.Path(__file__).parent.resolve() + dp_build_dir = run_config_provider( + ConfigProviderArguments( + return_dp_build_dir=True, + return_dp_source_dir=False, + return_llvm_bin_dir=False, + return_full_config=False, + return_version_string=False, + ) + ) + + env_vars = dict(os.environ) + + src_dir = os.path.join(current_dir, "src") + # create FileMapping + cmd = os.path.join(dp_build_dir, "scripts", "dp-fmap") + run_cmd(cmd, src_dir, env_vars) + + # build + env_vars["CC"] = os.path.join(dp_build_dir, "scripts", "CC_wrapper.sh") + env_vars["CXX"] = os.path.join(dp_build_dir, "scripts", "CXX_wrapper.sh") + env_vars["DP_PROJECT_ROOT_DIR"] = src_dir + cmd = "make" + run_cmd(cmd, src_dir, env_vars) + + # execute instrumented program + run_cmd("./prog", src_dir, env_vars) + + # execute DiscoPoP analysis + cmd = "discopop_explorer --enable-patterns doall,reduction" + run_cmd(cmd, os.path.join(src_dir, ".discopop"), env_vars) + + self.src_dir = src_dir + self.env_vars = env_vars + + test_output_file = os.path.join(self.src_dir, ".discopop", "explorer", "detection_result_dump.json") + # load detection results + with open(test_output_file, "r") as f: + tmp_str = f.read() + self.test_output: DetectionResult = jsonpickle.decode(tmp_str) + + @classmethod + def tearDownClass(self): + run_cmd("make veryclean", self.src_dir, self.env_vars) + + def test(self): + self.assertIn("do_all", self.test_output.patterns.__dict__) + doall_patterns = self.test_output.patterns.__dict__["do_all"] + self.assertEqual(len(doall_patterns), 1) + do_all_pattern = doall_patterns[0] + + expected_clauses: Dict[str, List[str]] = {"first_private": ["Arr"]} + + with self.subTest("check pattern for FP data sharing clauses"): + res, msg = check_clauses_for_FP(self, expected_clauses, do_all_pattern) + self.assertTrue(res, msg) + with self.subTest("check pattern for FN data sharing clauses"): + res, msg = check_clauses_for_FN(self, expected_clauses, do_all_pattern) + self.assertTrue(res, msg) + + diff --git a/test/wip_end_to_end/sharing_clauses/do_all/private/__init__.py b/test/wip_end_to_end/sharing_clauses/do_all/private/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/wip_end_to_end/sharing_clauses/do_all/private/case_2/__init__.py b/test/wip_end_to_end/sharing_clauses/do_all/private/case_2/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/wip_end_to_end/sharing_clauses/do_all/private/case_2/src/Makefile b/test/wip_end_to_end/sharing_clauses/do_all/private/case_2/src/Makefile new file mode 100644 index 000000000..8b1635880 --- /dev/null +++ b/test/wip_end_to_end/sharing_clauses/do_all/private/case_2/src/Makefile @@ -0,0 +1,15 @@ +all: clean prog + +prog: code.o + $(CXX) -o prog code.o $(CXXFLAGS) + +code.o: + $(CXX) -c -o code.o code.cpp $(CXXFLAGS) + +clean: + rm -rf .discopop + rm -rf src/.discopop + find . -not -name code.cpp -not -name Makefile -not -path **/FileMapping.txt -delete + +veryclean: clean + rm -f FileMapping.txt diff --git a/test/wip_end_to_end/sharing_clauses/do_all/private/case_2/src/code.cpp b/test/wip_end_to_end/sharing_clauses/do_all/private/case_2/src/code.cpp new file mode 100644 index 000000000..3b5440066 --- /dev/null +++ b/test/wip_end_to_end/sharing_clauses/do_all/private/case_2/src/code.cpp @@ -0,0 +1,16 @@ +#include +#include + +int main(int argc, const char *argv[]) { + static int n = 50000; + + double *Arr = (double *) malloc(n*sizeof(double)); + + // DO-ALL private(Arr) + for (int i = 0; i < n; i++) { + Arr[0] = i; + Arr[1] = i+2; + Arr[2] = i-4; + int x = Arr[0] + Arr[1] + Arr[2]; + } +} diff --git a/test/wip_end_to_end/sharing_clauses/do_all/private/case_2/test.py b/test/wip_end_to_end/sharing_clauses/do_all/private/case_2/test.py new file mode 100644 index 000000000..ece5f74da --- /dev/null +++ b/test/wip_end_to_end/sharing_clauses/do_all/private/case_2/test.py @@ -0,0 +1,82 @@ +import copy +import os +import pathlib +import subprocess +from typing import Dict, List +import unittest + +import jsonpickle + +from discopop_library.result_classes.DetectionResult import DetectionResult +from test.utils.sharing_clauses.clauses_utils import check_clauses_for_FN, check_clauses_for_FP +from test.utils.subprocess_wrapper.command_execution_wrapper import run_cmd +from test.utils.validator_classes.DoAllInfoForValidation import DoAllInfoForValidation +from subprocess import DEVNULL +from discopop_library.ConfigProvider.config_provider import run as run_config_provider +from discopop_library.ConfigProvider.ConfigProviderArguments import ConfigProviderArguments + + +class TestMethods(unittest.TestCase): + @classmethod + def setUpClass(self): + current_dir = pathlib.Path(__file__).parent.resolve() + dp_build_dir = run_config_provider( + ConfigProviderArguments( + return_dp_build_dir=True, + return_dp_source_dir=False, + return_llvm_bin_dir=False, + return_full_config=False, + return_version_string=False, + ) + ) + + env_vars = dict(os.environ) + + src_dir = os.path.join(current_dir, "src") + # create FileMapping + cmd = os.path.join(dp_build_dir, "scripts", "dp-fmap") + run_cmd(cmd, src_dir, env_vars) + + # build + env_vars["CC"] = os.path.join(dp_build_dir, "scripts", "CC_wrapper.sh") + env_vars["CXX"] = os.path.join(dp_build_dir, "scripts", "CXX_wrapper.sh") + env_vars["DP_PROJECT_ROOT_DIR"] = src_dir + cmd = "make" + run_cmd(cmd, src_dir, env_vars) + + # execute instrumented program + run_cmd("./prog", src_dir, env_vars) + + # execute DiscoPoP analysis + cmd = "discopop_explorer --enable-patterns doall,reduction" + run_cmd(cmd, os.path.join(src_dir, ".discopop"), env_vars) + + self.src_dir = src_dir + self.env_vars = env_vars + + test_output_file = os.path.join(self.src_dir, ".discopop", "explorer", "detection_result_dump.json") + # load detection results + with open(test_output_file, "r") as f: + tmp_str = f.read() + self.test_output: DetectionResult = jsonpickle.decode(tmp_str) + + @classmethod + def tearDownClass(self): + run_cmd("make veryclean", self.src_dir, self.env_vars) + + def test(self): + self.assertIn("do_all", self.test_output.patterns.__dict__) + doall_patterns = self.test_output.patterns.__dict__["do_all"] + self.assertEqual(len(doall_patterns), 1) + do_all_pattern = doall_patterns[0] + + expected_clauses: Dict[str, List[str]] = {"private": ["Arr"]} + + with self.subTest("check pattern for FP data sharing clauses"): + res, msg = check_clauses_for_FP(self, expected_clauses, do_all_pattern) + self.assertTrue(res, msg) + with self.subTest("check pattern for FN data sharing clauses"): + res, msg = check_clauses_for_FN(self, expected_clauses, do_all_pattern) + self.assertTrue(res, msg) + + From 833cc3ac4b8473dc510f5e70667689dc768dc8e6 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 23 Jul 2024 14:59:02 +0200 Subject: [PATCH 032/105] feat(explorer)[clauses]: improved detection of data sharing clauses (#642) * feat(explorer)[clauses]: improved detection of data sharing clauses * fixed test case and added wip_ test case for variable length array * fix: .addr tag not required anymore, replaced by GEPRESULT_ --- DiscoPoP/DiscoPoP.hpp | 8 +- .../low_level/instrumentAlloca.cpp | 2 +- .../low_level/instrumentLoad.cpp | 2 +- .../low_level/instrumentStore.cpp | 2 +- DiscoPoP/llvm_hooks/runOnFunction.cpp | 30 --- DiscoPoP/static_analysis/createCUs.cpp | 4 +- DiscoPoP/static_analysis/fillCUVariables.cpp | 2 +- .../populateGlobalVariablesSet.cpp | 2 +- DiscoPoP/utils/variables/defLine.cpp | 6 +- DiscoPoP/utils/variables/names.cpp | 34 ++- discopop_explorer/PEGraphX.py | 2 + discopop_explorer/parser.py | 16 +- .../pattern_detectors/reduction_detector.py | 1 + discopop_explorer/utils.py | 207 +++++++++++++++--- .../negative/case_1/src/code.cpp | 2 +- .../do_all/private/case_2}/__init__.py | 0 .../do_all/private/case_2/src/Makefile | 2 + .../do_all/private/case_2/src/code.cpp | 0 .../do_all/private/case_2/test.py | 0 .../case_2 => reduction_pattern}/__init__.py | 0 .../reduction_pattern/negative/__init__.py | 0 .../negative/case_2/__init__.py | 0 .../negative/case_2/src/Makefile | 17 ++ .../negative/case_2/src/code.cpp | 29 +++ .../reduction_pattern/negative/case_2/test.py | 85 +++++++ 25 files changed, 361 insertions(+), 92 deletions(-) rename test/{wip_end_to_end/sharing_clauses/do_all/private => end_to_end/sharing_clauses/do_all/private/case_2}/__init__.py (100%) rename test/{wip_end_to_end => end_to_end}/sharing_clauses/do_all/private/case_2/src/Makefile (79%) rename test/{wip_end_to_end => end_to_end}/sharing_clauses/do_all/private/case_2/src/code.cpp (100%) rename test/{wip_end_to_end => end_to_end}/sharing_clauses/do_all/private/case_2/test.py (100%) rename test/wip_end_to_end/{sharing_clauses/do_all/private/case_2 => reduction_pattern}/__init__.py (100%) create mode 100644 test/wip_end_to_end/reduction_pattern/negative/__init__.py create mode 100644 test/wip_end_to_end/reduction_pattern/negative/case_2/__init__.py create mode 100644 test/wip_end_to_end/reduction_pattern/negative/case_2/src/Makefile create mode 100644 test/wip_end_to_end/reduction_pattern/negative/case_2/src/code.cpp create mode 100644 test/wip_end_to_end/reduction_pattern/negative/case_2/test.py diff --git a/DiscoPoP/DiscoPoP.hpp b/DiscoPoP/DiscoPoP.hpp index 1d846147e..d79438360 100644 --- a/DiscoPoP/DiscoPoP.hpp +++ b/DiscoPoP/DiscoPoP.hpp @@ -71,14 +71,14 @@ #define DP_DEBUG false #define ClCheckLoopPar true -#define DumpToDot true +#define DumpToDot false #define DP_BRANCH_TRACKING \ true // toggles the creation of instrumentation calls for tracking taken // branches. Required by the graph pruning step of the DiscoPoP // optimizer. #define DP_DEBUG false #define DP_VERBOSE false // prints warning messages -#define DP_hybrid_DEBUG true +#define DP_hybrid_DEBUG false using namespace llvm; using namespace std; @@ -137,10 +137,10 @@ class DiscoPoP : public ModulePass { Type *pointsToStruct(PointerType *PTy); - Value *determineVariableName_dynamic(Instruction *const I); + Value *determineVariableName_dynamic(Instruction *const I, string prefix); string determineVariableName_static(Instruction *I, bool &isGlobalVariable /*=defaultIsGlobalVariableValue*/, - bool disable_MetadataMap); + bool disable_MetadataMap, string prefix); void getTrueVarNamesFromMetadata(Region *TopRegion, Node *root, std::map *trueVarNamesFromMetadataMap); diff --git a/DiscoPoP/instrumentation/low_level/instrumentAlloca.cpp b/DiscoPoP/instrumentation/low_level/instrumentAlloca.cpp index 407160a42..675251782 100644 --- a/DiscoPoP/instrumentation/low_level/instrumentAlloca.cpp +++ b/DiscoPoP/instrumentation/low_level/instrumentAlloca.cpp @@ -24,7 +24,7 @@ void DiscoPoP::instrumentAlloca(AllocaInst *toInstrument) { vector args; args.push_back(ConstantInt::get(Int32, lid)); - args.push_back(determineVariableName_dynamic(toInstrument)); + args.push_back(determineVariableName_dynamic(toInstrument, "")); bool isGlobal; // Value *startAddr = PtrToIntInst::CreatePointerCast(toInstrument, Int64, "", diff --git a/DiscoPoP/instrumentation/low_level/instrumentLoad.cpp b/DiscoPoP/instrumentation/low_level/instrumentLoad.cpp index 511f92d03..2c97b5b5b 100644 --- a/DiscoPoP/instrumentation/low_level/instrumentLoad.cpp +++ b/DiscoPoP/instrumentation/low_level/instrumentLoad.cpp @@ -25,7 +25,7 @@ void DiscoPoP::instrumentLoad(LoadInst *toInstrument) { Value *memAddr = PtrToIntInst::CreatePointerCast(toInstrument->getPointerOperand(), Int64, "", toInstrument); args.push_back(memAddr); - args.push_back(determineVariableName_dynamic(toInstrument)); + args.push_back(determineVariableName_dynamic(toInstrument, "")); #ifdef SKIP_DUP_INSTR Twine name = Twine("L").concat(Twine(uniqueNum)); diff --git a/DiscoPoP/instrumentation/low_level/instrumentStore.cpp b/DiscoPoP/instrumentation/low_level/instrumentStore.cpp index daf3afe74..b09db4326 100644 --- a/DiscoPoP/instrumentation/low_level/instrumentStore.cpp +++ b/DiscoPoP/instrumentation/low_level/instrumentStore.cpp @@ -24,7 +24,7 @@ void DiscoPoP::instrumentStore(StoreInst *toInstrument) { Value *memAddr = PtrToIntInst::CreatePointerCast(toInstrument->getPointerOperand(), Int64, "", toInstrument); args.push_back(memAddr); - args.push_back(determineVariableName_dynamic(toInstrument)); + args.push_back(determineVariableName_dynamic(toInstrument, "")); #ifdef SKIP_DUP_INSTR Twine name = Twine("S").concat(Twine(uniqueNum)); diff --git a/DiscoPoP/llvm_hooks/runOnFunction.cpp b/DiscoPoP/llvm_hooks/runOnFunction.cpp index 97283df47..f85dd0c88 100644 --- a/DiscoPoP/llvm_hooks/runOnFunction.cpp +++ b/DiscoPoP/llvm_hooks/runOnFunction.cpp @@ -283,9 +283,6 @@ bool DiscoPoP::runOnFunction(Function &F) { if(DG.edgeIsINIT(edge)){ string initLine = DG.getInitEdgeInstructionLine(edge); string varIdentifier = DG.getValueNameAndMemRegIDFromEdge(edge, staticValueNameToMemRegIDMap); - std::cout << "Found init: " << DG.edgeToDPDep(edge, staticValueNameToMemRegIDMap) << "\n"; - std::cout << "\t@ " << initLine << "\n"; - std::cout << "\tvar: " << varIdentifier << "\n"; if(lineToInitializedVarsMap.find(initLine) == lineToInitializedVarsMap.end()){ set tmp; @@ -310,52 +307,26 @@ bool DiscoPoP::runOnFunction(Function &F) { if (!conditionalBBDepMap.count(Src->getParent())) { set tmp; conditionalBBDepMap[Src->getParent()] = tmp; - - std::cout<< "Registered set1: \n"; - for(auto s : tmp){ - std::cout << "--> " << s << "\n"; - } } conditionalBBDepMap[Src->getParent()].insert(DG.edgeToDPDep(edge, staticValueNameToMemRegIDMap)); - std::cout << "Inserted1: " << DG.edgeToDPDep(edge, staticValueNameToMemRegIDMap) << "\n"; } else { if (!conditionalBBPairDepMap.count(Dst->getParent())) { map> tmp; conditionalBBPairDepMap[Dst->getParent()] = tmp; - std::cout<< "Registered set2: \n"; - for(auto pair : tmp){ - for(auto s : pair.second){ - std::cout << "--> " << s << "\n"; - } - } } if (!conditionalBBPairDepMap[Dst->getParent()].count(Src->getParent())) { set tmp; conditionalBBPairDepMap[Dst->getParent()][Src->getParent()] = tmp; - std::cout<< "Registered set3: \n"; - for(auto s : tmp){ - std::cout << "--> " << s << "\n"; - } } - std::cout << "First: " << Dst << "\n"; - Dst->print(outs()); - std::cout << "\n"; - std::cout << "Second: " << Src << "\n"; - Src->print(outs()); - std::cout << "\n"; // Prevent reporting of false-positive WAW Dependencies due to alloca movement from e.g. loops to function entry bool insertDep = true; if(Dst == Src){ // check if instruciton are the same - std::cout << "==> Potential for false-positive WAW\n"; - std::cout << "--> same inst\n"; // check if initialization exists in the instruction line if(lineToInitializedVarsMap.find(DG.getInstructionLine(Dst)) != lineToInitializedVarsMap.end()){ - std::cout << "--> same init exists\n"; // check if the accessed variable is initialed here string varIdentifier = DG.getValueNameAndMemRegIDFromEdge(edge, staticValueNameToMemRegIDMap); if(lineToInitializedVarsMap[DG.getInstructionLine(Dst)].find(varIdentifier) != lineToInitializedVarsMap[DG.getInstructionLine(Dst)].end()){ // ignore this access as the initialized variable is accessed - std::cout << "==> initialized var accessed\n"; insertDep = false; } } @@ -364,7 +335,6 @@ bool DiscoPoP::runOnFunction(Function &F) { if(insertDep){ conditionalBBPairDepMap[Dst->getParent()][Src->getParent()].insert( DG.edgeToDPDep(edge, staticValueNameToMemRegIDMap)); - std::cout << "Inserted: " << DG.edgeToDPDep(edge, staticValueNameToMemRegIDMap) << "\n"; } } omittableInstructions.insert(Src); diff --git a/DiscoPoP/static_analysis/createCUs.cpp b/DiscoPoP/static_analysis/createCUs.cpp index 43bbe981b..3f972fc5f 100644 --- a/DiscoPoP/static_analysis/createCUs.cpp +++ b/DiscoPoP/static_analysis/createCUs.cpp @@ -152,7 +152,7 @@ void DiscoPoP::createCUs(Region *TopRegion, set &globalVariablesSet, vec Type *Ty = operand->getType(); unsigned u = DL->getTypeSizeInBits(Ty); cu->writeDataSize += u; - varName = determineVariableName_static(&*instruction, isGlobalVar, false); + varName = determineVariableName_static(&*instruction, isGlobalVar, false, ""); varType = determineVariableType(&*instruction); suspiciousVariables.insert(varName); if (lid > 0) @@ -162,7 +162,7 @@ void DiscoPoP::createCUs(Region *TopRegion, set &globalVariablesSet, vec Type *Ty = instruction->getType(); unsigned u = DL->getTypeSizeInBits(Ty); cu->readDataSize += u; - varName = determineVariableName_static(&*instruction, isGlobalVar, false); + varName = determineVariableName_static(&*instruction, isGlobalVar, false, ""); if (suspiciousVariables.count(varName)) { // VIOLATION OF CAUTIOUS PROPERTY // it is a load instruction which read the value of a global diff --git a/DiscoPoP/static_analysis/fillCUVariables.cpp b/DiscoPoP/static_analysis/fillCUVariables.cpp index 3afa00781..dd128660a 100644 --- a/DiscoPoP/static_analysis/fillCUVariables.cpp +++ b/DiscoPoP/static_analysis/fillCUVariables.cpp @@ -41,7 +41,7 @@ void DiscoPoP::fillCUVariables(Region *TopRegion, set &globalVariablesSe if (lid == 0) continue; // NOTE: changed 'instruction' to '&*instruction', next 2 lines - varName = determineVariableName_static(&*instruction, isGlobalVar, false); + varName = determineVariableName_static(&*instruction, isGlobalVar, false, ""); varType = determineVariableType(&*instruction); int index = isa(&*instruction) ? 1 : 0; diff --git a/DiscoPoP/static_analysis/populateGlobalVariablesSet.cpp b/DiscoPoP/static_analysis/populateGlobalVariablesSet.cpp index 9af29c78e..1dfe9bc44 100644 --- a/DiscoPoP/static_analysis/populateGlobalVariablesSet.cpp +++ b/DiscoPoP/static_analysis/populateGlobalVariablesSet.cpp @@ -23,7 +23,7 @@ void DiscoPoP::populateGlobalVariablesSet(Region *TopRegion, set &global if (isa(instruction) || isa(instruction) || isa(instruction)) { // NOTE: changed 'instruction' to '&*instruction' - string varName = determineVariableName_static(&*instruction, isGlobalVariable, false); + string varName = determineVariableName_static(&*instruction, isGlobalVariable, false, ""); if (isGlobalVariable) // add it if it is a global variable in the // program diff --git a/DiscoPoP/utils/variables/defLine.cpp b/DiscoPoP/utils/variables/defLine.cpp index 308bebc0f..3cebc1c14 100644 --- a/DiscoPoP/utils/variables/defLine.cpp +++ b/DiscoPoP/utils/variables/defLine.cpp @@ -16,7 +16,7 @@ string DiscoPoP::determineVariableDefLine(Instruction *I) { string varDefLine{"LineNotFound"}; bool isGlobal = false; - string varName = determineVariableName_static(&*I, isGlobal, true); + string varName = determineVariableName_static(&*I, isGlobal, true, ""); // varName = refineVarName(varName); varName = (varName.find(".addr") == varName.npos) ? varName : varName.erase(varName.find(".addr"), 5); // varName.erase(varName.find(".addr"), 5); @@ -63,10 +63,10 @@ string DiscoPoP::determineVariableDefLine(Instruction *I) { if (AI) { for (User *U : AI->users()) { if (StoreInst *SI = dyn_cast(U)) { - vn = determineVariableName_static(&*SI, isGlobal, true); + vn = determineVariableName_static(&*SI, isGlobal, true, ""); break; } else if (LoadInst *LI = dyn_cast(U)) { - vn = determineVariableName_static(&*LI, isGlobal, true); + vn = determineVariableName_static(&*LI, isGlobal, true, ""); break; } } diff --git a/DiscoPoP/utils/variables/names.cpp b/DiscoPoP/utils/variables/names.cpp index 0d5886f65..e96ff7e0b 100644 --- a/DiscoPoP/utils/variables/names.cpp +++ b/DiscoPoP/utils/variables/names.cpp @@ -14,6 +14,11 @@ string DiscoPoP::getOrInsertVarName_static(string varName, IRBuilder<> &builder) { Value *valName = NULL; + // remove .addr if added. Replaced by the GEPRESULT_ tag + if (varName.find(".addr") != std::string::npos){ + varName.erase(varName.find(".addr"), 5); + } + std::string vName = varName; map::iterator pair = VarNames.find(varName); if (pair == VarNames.end()) { @@ -28,6 +33,11 @@ string DiscoPoP::getOrInsertVarName_static(string varName, IRBuilder<> &builder) } Value *DiscoPoP::getOrInsertVarName_dynamic(string varName, IRBuilder<> &builder) { + // remove .addr if added. Replaced by the GEPRESULT_ tag + if (varName.find(".addr") != std::string::npos){ + varName.erase(varName.find(".addr"), 5); + } + // 26.08.2022 Lukas // update varName with original varName from Metadata if (trueVarNamesFromMetadataMap.find(varName) == trueVarNamesFromMetadataMap.end()) { @@ -49,7 +59,7 @@ Value *DiscoPoP::getOrInsertVarName_dynamic(string varName, IRBuilder<> &builder } string DiscoPoP::determineVariableName_static(Instruction *I, bool &isGlobalVariable /*=defaultIsGlobalVariableValue*/, - bool disable_MetadataMap) { + bool disable_MetadataMap, string prefix) { assert(I && "Instruction cannot be NULL \n"); int index = isa(I) ? 1 : 0; @@ -120,9 +130,9 @@ string DiscoPoP::determineVariableName_static(Instruction *I, bool &isGlobalVari // we've found an array if (PTy->getPointerElementType()->getTypeID() == Type::ArrayTyID && isa(*ptrOperand)) { - return determineVariableName_static((Instruction *)ptrOperand, isGlobalVariable, false); + return determineVariableName_static((Instruction *)ptrOperand, isGlobalVariable, false, prefix); } - return determineVariableName_static((Instruction *)gep, isGlobalVariable, false); + return determineVariableName_static((Instruction *)gep, isGlobalVariable, false, "GEPRESULT_" + prefix); } string retVal = string(operand->getName().data()); if (trueVarNamesFromMetadataMap.find(retVal) == trueVarNamesFromMetadataMap.end() || disable_MetadataMap) { @@ -134,13 +144,13 @@ string DiscoPoP::determineVariableName_static(Instruction *I, bool &isGlobalVari } if (isa(*operand) || isa(*operand)) { - return determineVariableName_static((Instruction *)(operand), isGlobalVariable, false); + return determineVariableName_static((Instruction *)(operand), isGlobalVariable, false, prefix); } // if we cannot determine the name, then return * return ""; // getOrInsertVarName("*", builder); } -Value *DiscoPoP::determineVariableName_dynamic(Instruction *const I) { +Value *DiscoPoP::determineVariableName_dynamic(Instruction *const I, string prefix) { assert(I && "Instruction cannot be NULL \n"); int index = isa(I) ? 1 : 0; Value *operand = I->getOperand(index); @@ -156,7 +166,7 @@ Value *DiscoPoP::determineVariableName_dynamic(Instruction *const I) { if (isa(*operand)) { DIGlobalVariable *gv = findDbgGlobalDeclare(cast(operand)); if (gv != NULL) { - return getOrInsertVarName_dynamic(string(gv->getDisplayName().data()), builder); + return getOrInsertVarName_dynamic(prefix + string(gv->getDisplayName().data()), builder); } } if (isa(*operand)) { @@ -187,21 +197,21 @@ Value *DiscoPoP::determineVariableName_dynamic(Instruction *const I) { // we've found an array if (PTy->getPointerElementType()->getTypeID() == Type::ArrayTyID && isa(*ptrOperand)) { - return determineVariableName_dynamic((Instruction *)ptrOperand); + return determineVariableName_dynamic((Instruction *)ptrOperand, prefix); } - return determineVariableName_dynamic((Instruction *)gep); + return determineVariableName_dynamic((Instruction *)gep, "GEPRESULT_"+prefix); } - return getOrInsertVarName_dynamic(string(operand->getName().data()), builder); + return getOrInsertVarName_dynamic(prefix + string(operand->getName().data()), builder); } if (isa(*operand) || isa(*operand)) { - return determineVariableName_dynamic((Instruction *)(operand)); + return determineVariableName_dynamic((Instruction *)(operand), prefix); } if (isa(I)) { - return getOrInsertVarName_dynamic(I->getName().str(), builder); + return getOrInsertVarName_dynamic(prefix + I->getName().str(), builder); } // if we cannot determine the name, then return * - return getOrInsertVarName_dynamic("*", builder); + return getOrInsertVarName_dynamic(prefix + "*", builder); } void DiscoPoP::getTrueVarNamesFromMetadata(Region *TopRegion, Node *root, diff --git a/discopop_explorer/PEGraphX.py b/discopop_explorer/PEGraphX.py index 2b0bcfec3..d7840b6b2 100644 --- a/discopop_explorer/PEGraphX.py +++ b/discopop_explorer/PEGraphX.py @@ -738,6 +738,8 @@ def map_static_and_dynamic_dependencies(self) -> None: if d1.memory_region != d2.memory_region: if d1.memory_region is None or d2.memory_region is None: continue + if d1.memory_region.startswith("GEPRESULT_") or d2.memory_region.startswith("GEPRESULT_"): + continue if d1.memory_region not in mem_reg_mappings: mem_reg_mappings[d1.memory_region] = set() if d2.memory_region not in mem_reg_mappings: diff --git a/discopop_explorer/parser.py b/discopop_explorer/parser.py index 22d46c6e8..9b8b4ff26 100644 --- a/discopop_explorer/parser.py +++ b/discopop_explorer/parser.py @@ -33,6 +33,7 @@ class DependenceItem(object): type: Any var_name: Any memory_region: Any + is_gep_result_dependency: bool metadata: Any # TODO improve typing @@ -198,13 +199,24 @@ def __parse_dep_file(dep_fd: TextIOWrapper, output_path: str) -> Tuple[List[Depe key_tuple = sink, source_fields[0], type, var_name, aa_var_name if key_tuple in dependency_metadata: metadata = dependency_metadata[key_tuple] + + # check if the dependency originates from the result of a GEP instruction + is_gep_result_dependency = False + if var_name.startswith("GEPRESULT_"): + var_name = var_name.replace("GEPRESULT_", "") + is_gep_result_dependency = True + # register dependencies if len(metadata) == 0: - dependencies_list.append(DependenceItem(sink, source_fields[0], type, var_name, aa_var_name, "")) + dependencies_list.append( + DependenceItem(sink, source_fields[0], type, var_name, aa_var_name, is_gep_result_dependency, "") + ) else: for md_set in metadata: dependencies_list.append( - DependenceItem(sink, source_fields[0], type, var_name, aa_var_name, md_set) + DependenceItem( + sink, source_fields[0], type, var_name, aa_var_name, is_gep_result_dependency, md_set + ) ) return dependencies_list, loop_data_list diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index 3b4be08c9..12706cd5d 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -145,6 +145,7 @@ def __detect_reduction(pet: PEGraphX, root: LoopNode) -> bool: # and "**" not in v.type --> replaced by check for array reduction ] reduction_var_names = cast(List[str], [v.name for v in reduction_vars]) + fp, p, lp, s, r = classify_loop_variables(pet, root) # get parents of loop diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index 146aab72f..02e8ca60b 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -685,51 +685,100 @@ def classify_loop_variables( ) # vars = list(pet.get_variables(sub)) + metadata_safe_index_accesses: List[Variable] = [] for var in vars: - if is_loop_index2(pet, loop, var.name): - if is_read_in_subtree(vars[var], rev_raw, rst): - last_private.append(var) - else: - private.append(var) - elif loop.reduction and pet.is_reduction_var(loop.start_position(), var.name): - var.operation = pet.get_reduction_sign(loop.start_position(), var.name) - reduction.append(var) - elif is_written_in_subtree(vars[var], raw, waw, lst) or is_func_arg(pet, var.name, loop) and is_scalar_val(var): - if is_readonly(vars[var], war, waw, rev_raw): - if is_global(var.name, sub): - shared.append(var) - else: - first_private.append(var) - elif is_read_in_subtree(vars[var], rev_raw, rst): - if is_scalar_val(var): + if loop.start_position() == "1:281" and (var.name == "d" or var.name == "d2"): + pass + # separate pointer and pointee dependencies for separated clasification + # classifications will be merged before returning + non_gep_mem_regs = set([mr for mr in vars[var] if not mr.startswith("GEPRESULT_")]) + gep_mem_regs = set([mr for mr in vars[var] if mr.startswith("GEPRESULT_")]) + + for subset_idx, mem_reg_subset in enumerate([non_gep_mem_regs, gep_mem_regs]): + if subset_idx > 0 and len(mem_reg_subset) == 0: + continue + if is_loop_index2(pet, loop, var.name): + if is_read_in_subtree(mem_reg_subset, rev_raw, rst): last_private.append(var) else: - shared.append(var) - else: - if not is_scalar_val(var): - # array type variable is written - shared.append(var) - else: - if is_first_written(vars[var], raw, waw, sub): - private.append(var) + private.append(var) + elif loop.reduction and pet.is_reduction_var(loop.start_position(), var.name): + var.operation = pet.get_reduction_sign(loop.start_position(), var.name) + reduction.append(var) + elif ( + is_written_in_subtree(mem_reg_subset, raw, waw, lst) + or is_func_arg(pet, var.name, loop) + and is_scalar_val(var) + ): + if is_readonly(mem_reg_subset, war, waw, rev_raw): + if is_global(var.name, sub): + shared.append(var) else: first_private.append(var) - - elif is_first_written(vars[var], raw, war, sub): - if len(vars[var].intersection(initialized_memory_regions)) > 0: - # variable is initialized in loop. No data sharing clauses required. - pass - else: - if is_read_in_subtree(vars[var], rev_raw, rst): + elif is_read_in_subtree(mem_reg_subset, rev_raw, rst): if is_scalar_val(var): last_private.append(var) else: shared.append(var) else: - if is_scalar_val(var): + if not is_scalar_val(var): + # array type variable is written + shared.append(var) + else: + if is_first_written(mem_reg_subset, raw, waw, sub): + private.append(var) + else: + first_private.append(var) + + elif is_first_written(mem_reg_subset, raw, war, sub): + if len(mem_reg_subset.intersection(initialized_memory_regions)) > 0 and subset_idx < 1: + # subset_idx < 1 to ignore this check for gep memory regions, as they create additional INIT dependencies + # variable is initialized in loop. + + # No data sharing clauses required, if the variable is declared inside the loop. + if var_declared_in_subtree(var, sub): + pass + # Else, the variable requires a private clause + else: private.append(var) + else: + if is_read_in_subtree(mem_reg_subset, rev_raw, rst): + if is_scalar_val(var): + last_private.append(var) + else: + shared.append(var) else: - shared.append(var) + # do not distinguish between scalar and structure types + private.append(var) + # keep old code until above replacement is proven to work + # BEGIN: OLD CODE + # if is_scalar_val(var): + # private.append(var) + # else: + # shared.append(var) + # END: OLD CODE + if subset_idx >= 1 and no_inter_iteration_dependency_exists( + mem_reg_subset, raw, war, sub, cast(LoopNode, loop) + ): + # check if metadata suggests, that index accesses are not problematic wrt. parallelization + metadata_safe_index_accesses.append(var) + + if loop.start_position() == "1:281": + pass + # modify classifications + first_private, private, last_private, shared, reduction = __modify_classifications( + first_private, private, last_private, shared, reduction, metadata_safe_index_accesses + ) + + if loop.start_position() == "1:281": + pass + # merge classifications + first_private, private, last_private, shared, reduction = __merge_classifications( + first_private, private, last_private, shared, reduction + ) + + if loop.start_position() == "1:281": + pass # return first_private, private, last_private, shared, reduction return ( sorted(first_private), @@ -740,6 +789,98 @@ def classify_loop_variables( ) +def var_declared_in_subtree(var: Variable, sub: list[CUNode]) -> bool: + var_file_id = int(var.defLine.split(":")[0]) + var_def_line = int(var.defLine.split(":")[1]) + for node in sub: + if (node.file_id == var_file_id) and (node.start_line <= var_def_line) and (node.end_line >= var_def_line): + return True + return False + + +def no_inter_iteration_dependency_exists( + mem_regs: Set[MemoryRegion], + raw: Set[Tuple[NodeID, NodeID, Dependency]], + war: Set[Tuple[NodeID, NodeID, Dependency]], + sub: List[CUNode], + root_loop: LoopNode, +) -> bool: + + for dep in raw.union(war): + if dep[0] in [s.id for s in sub] and dep[1] in [s.id for s in sub]: + if dep[2].memory_region in mem_regs: + if root_loop.start_position() in dep[2].metadata_inter_iteration_dep: + return False + return True + + +def __modify_classifications( + first_private: list[Variable], + private: list[Variable], + last_private: list[Variable], + shared: list[Variable], + reduction: list[Variable], + metadata_safe_index_accesses: list[Variable], +) -> Tuple[list[Variable], list[Variable], list[Variable], list[Variable], list[Variable]]: + # Rule 1: if structure index accesses suggest, that parallelizing is safe without data sharing clauses, loosen private clauses to shared. + # --> this rule does not affect first_ and last_private clauses, as they require a specific access / dependency pattern + move_to_shared: List[Variable] = [] + for var in metadata_safe_index_accesses: + if var in private: + move_to_shared.append(var) + for var in move_to_shared: + if var in private: + private.remove(var) + if var not in shared: + shared.append(var) + + return first_private, private, last_private, shared, reduction + + +def __merge_classifications( + first_private: list[Variable], + private: list[Variable], + last_private: list[Variable], + shared: list[Variable], + reduction: list[Variable], +) -> Tuple[list[Variable], list[Variable], list[Variable], list[Variable], list[Variable]]: + new_first_private: list[Variable] = [] + new_private: list[Variable] = [] + new_last_private: list[Variable] = [] + new_shared: list[Variable] = [] + new_reduction: list[Variable] = reduction + + remove_from_private: Set[Variable] = set() + remove_from_first_private: Set[Variable] = set() + remove_from_last_private: Set[Variable] = set() + remove_from_shared: Set[Variable] = set() + remove_from_reduction: Set[Variable] = set() + + # Rule 1: firstprivate is more restrictive than private + for var_1 in first_private: + for var_2 in private: + if var_1.name == var_2.name: + remove_from_private.add(var_2) + # Rule 2: lastprivate is more restrictive than private + for var_1 in last_private: + for var_2 in private: + if var_1.name == var_2.name: + remove_from_private.add(var_2) + # Rule 3: shared is less restrictive than any private + for var_1 in first_private + last_private + private: + for var_2 in shared: + if var_1.name == var_2.name: + remove_from_shared.add(var_2) + + new_first_private = [v for v in first_private if v not in remove_from_first_private] + new_last_private = [v for v in last_private if v not in remove_from_last_private] + new_private = [v for v in private if v not in remove_from_private] + new_shared = [v for v in shared if v not in remove_from_shared] + new_reduction = [v for v in reduction if v not in remove_from_reduction] + + return new_first_private, new_private, new_last_private, new_shared, new_reduction + + def classify_task_vars( pet: PEGraphX, task: Node, diff --git a/test/end_to_end/reduction_pattern/negative/case_1/src/code.cpp b/test/end_to_end/reduction_pattern/negative/case_1/src/code.cpp index 35859565c..aef86e8a8 100644 --- a/test/end_to_end/reduction_pattern/negative/case_1/src/code.cpp +++ b/test/end_to_end/reduction_pattern/negative/case_1/src/code.cpp @@ -12,7 +12,7 @@ int g(int i) { return i; } int main() { int N = 100000; - int Arr[N]; + int Arr[100000]; // DOALL for (int i = 0; i < N; i++) { diff --git a/test/wip_end_to_end/sharing_clauses/do_all/private/__init__.py b/test/end_to_end/sharing_clauses/do_all/private/case_2/__init__.py similarity index 100% rename from test/wip_end_to_end/sharing_clauses/do_all/private/__init__.py rename to test/end_to_end/sharing_clauses/do_all/private/case_2/__init__.py diff --git a/test/wip_end_to_end/sharing_clauses/do_all/private/case_2/src/Makefile b/test/end_to_end/sharing_clauses/do_all/private/case_2/src/Makefile similarity index 79% rename from test/wip_end_to_end/sharing_clauses/do_all/private/case_2/src/Makefile rename to test/end_to_end/sharing_clauses/do_all/private/case_2/src/Makefile index 8b1635880..4bc2f0c44 100644 --- a/test/wip_end_to_end/sharing_clauses/do_all/private/case_2/src/Makefile +++ b/test/end_to_end/sharing_clauses/do_all/private/case_2/src/Makefile @@ -4,6 +4,8 @@ prog: code.o $(CXX) -o prog code.o $(CXXFLAGS) code.o: + $(CXX) -c -S -emit-llvm -o code.ll code.cpp $(CXXFLAGS) + rm -r .discopop $(CXX) -c -o code.o code.cpp $(CXXFLAGS) clean: diff --git a/test/wip_end_to_end/sharing_clauses/do_all/private/case_2/src/code.cpp b/test/end_to_end/sharing_clauses/do_all/private/case_2/src/code.cpp similarity index 100% rename from test/wip_end_to_end/sharing_clauses/do_all/private/case_2/src/code.cpp rename to test/end_to_end/sharing_clauses/do_all/private/case_2/src/code.cpp diff --git a/test/wip_end_to_end/sharing_clauses/do_all/private/case_2/test.py b/test/end_to_end/sharing_clauses/do_all/private/case_2/test.py similarity index 100% rename from test/wip_end_to_end/sharing_clauses/do_all/private/case_2/test.py rename to test/end_to_end/sharing_clauses/do_all/private/case_2/test.py diff --git a/test/wip_end_to_end/sharing_clauses/do_all/private/case_2/__init__.py b/test/wip_end_to_end/reduction_pattern/__init__.py similarity index 100% rename from test/wip_end_to_end/sharing_clauses/do_all/private/case_2/__init__.py rename to test/wip_end_to_end/reduction_pattern/__init__.py diff --git a/test/wip_end_to_end/reduction_pattern/negative/__init__.py b/test/wip_end_to_end/reduction_pattern/negative/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/wip_end_to_end/reduction_pattern/negative/case_2/__init__.py b/test/wip_end_to_end/reduction_pattern/negative/case_2/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/wip_end_to_end/reduction_pattern/negative/case_2/src/Makefile b/test/wip_end_to_end/reduction_pattern/negative/case_2/src/Makefile new file mode 100644 index 000000000..a64882be3 --- /dev/null +++ b/test/wip_end_to_end/reduction_pattern/negative/case_2/src/Makefile @@ -0,0 +1,17 @@ +all: clean prog + +prog: code.o + $(CXX) -o prog code.o $(CXXFLAGS) + +code.o: + $(CXX) -c -S -emit-llvm -o code.ll code.cpp $(CXXFLAGS) + rm -rf .discopop + $(CXX) -c -o code.o code.cpp $(CXXFLAGS) + +clean: + rm -rf .discopop + rm -rf src/.discopop + find . -not -name code.cpp -not -name Makefile -not -path **/FileMapping.txt -delete + +veryclean: clean + rm -f FileMapping.txt diff --git a/test/wip_end_to_end/reduction_pattern/negative/case_2/src/code.cpp b/test/wip_end_to_end/reduction_pattern/negative/case_2/src/code.cpp new file mode 100644 index 000000000..35859565c --- /dev/null +++ b/test/wip_end_to_end/reduction_pattern/negative/case_2/src/code.cpp @@ -0,0 +1,29 @@ +#include + +int f(int i) { + if (i < 100000 / 2) { + return i + 100000 / 2; + } else { + return i; + } +} + +int g(int i) { return i; } + +int main() { + int N = 100000; + int Arr[N]; + + // DOALL + for (int i = 0; i < N; i++) { + Arr[i] = 0; + } + + long w = 0; + + // NO REDUCTION, NO DOALL + for (int i = 0; i < N; i++) { + w += Arr[g(i)]; + Arr[f(i)] = 1; + } +} \ No newline at end of file diff --git a/test/wip_end_to_end/reduction_pattern/negative/case_2/test.py b/test/wip_end_to_end/reduction_pattern/negative/case_2/test.py new file mode 100644 index 000000000..102624dc2 --- /dev/null +++ b/test/wip_end_to_end/reduction_pattern/negative/case_2/test.py @@ -0,0 +1,85 @@ +import copy +import os +import pathlib +import unittest + +import jsonpickle + +from discopop_library.result_classes.DetectionResult import DetectionResult +from test.utils.existence.existence_utils import check_patterns_for_FN, check_patterns_for_FP +from test.utils.subprocess_wrapper.command_execution_wrapper import run_cmd +from test.utils.validator_classes.DoAllInfoForValidation import DoAllInfoForValidation +from discopop_library.ConfigProvider.config_provider import run as run_config_provider +from discopop_library.ConfigProvider.ConfigProviderArguments import ConfigProviderArguments + + +class TestMethods(unittest.TestCase): + @classmethod + def setUpClass(self): + current_dir = pathlib.Path(__file__).parent.resolve() + dp_build_dir = run_config_provider( + ConfigProviderArguments( + return_dp_build_dir=True, + return_dp_source_dir=False, + return_llvm_bin_dir=False, + return_full_config=False, + return_version_string=False, + ) + ) + + env_vars = dict(os.environ) + + src_dir = os.path.join(current_dir, "src") + + # create FileMapping + cmd = os.path.join(dp_build_dir, "scripts", "dp-fmap") + run_cmd(cmd, src_dir, env_vars) + + # build + env_vars["CC"] = os.path.join(dp_build_dir, "scripts", "CC_wrapper.sh") + env_vars["CXX"] = os.path.join(dp_build_dir, "scripts", "CXX_wrapper.sh") + env_vars["DP_PROJECT_ROOT_DIR"] = src_dir + cmd = "make" + run_cmd(cmd, src_dir, env_vars) + # execute instrumented program + cmd = "./prog" + run_cmd(cmd, src_dir, env_vars) + # execute DiscoPoP analysis + cwd = os.path.join(src_dir, ".discopop") + cmd = "discopop_explorer --enable-patterns doall,reduction" + run_cmd(cmd, cwd, env_vars) + + self.src_dir = src_dir + self.env_vars = env_vars + + test_output_file = os.path.join(self.src_dir, ".discopop", "explorer", "detection_result_dump.json") + # load detection results + with open(test_output_file, "r") as f: + tmp_str = f.read() + self.test_output: DetectionResult = jsonpickle.decode(tmp_str) + + @classmethod + def tearDownClass(self): + run_cmd("make veryclean", self.src_dir, self.env_vars) + + def test(self): + for pattern_type in self.test_output.patterns.__dict__: + amount_of_identified_patterns = len(self.test_output.patterns.__dict__[pattern_type]) + if pattern_type == "do_all": + expected_lines = ["1:18"] + with self.subTest("check for FP"): + res, msg = check_patterns_for_FP(self, pattern_type, copy.deepcopy(expected_lines), self.test_output.patterns.__dict__[pattern_type]) + self.assertTrue(res, msg) + with self.subTest("check for FN"): + res, msg = check_patterns_for_FN(self, pattern_type, copy.deepcopy(expected_lines), self.test_output.patterns.__dict__[pattern_type]) + self.assertTrue(res, msg) + elif pattern_type == "reduction": + expected_lines = [] + with self.subTest("check for FP"): + res, msg = check_patterns_for_FP(self, pattern_type, copy.deepcopy(expected_lines), self.test_output.patterns.__dict__[pattern_type]) + self.assertTrue(res, msg) + with self.subTest("check for FN"): + res, msg = check_patterns_for_FN(self, pattern_type, copy.deepcopy(expected_lines), self.test_output.patterns.__dict__[pattern_type]) + self.assertTrue(res, msg) + else: + self.assertEqual(amount_of_identified_patterns, 0) From df49c93134695479b9cc3875b5d2857caf088d78 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 23 Jul 2024 15:20:06 +0200 Subject: [PATCH 033/105] feat(autotuner): create statistics graph output (#643) * feat(autotuner): create statistics graph output --- .../EmpiricalAutotuning/Autotuner.py | 68 +++++++++++++++- .../Classes/CodeConfiguration.py | 23 +++++- .../Statistics/StatisticsGraph.py | 79 +++++++++++++++++++ setup.py | 1 + 4 files changed, 169 insertions(+), 2 deletions(-) create mode 100644 discopop_library/EmpiricalAutotuning/Statistics/StatisticsGraph.py diff --git a/discopop_library/EmpiricalAutotuning/Autotuner.py b/discopop_library/EmpiricalAutotuning/Autotuner.py index 735002fd4..68cf81246 100644 --- a/discopop_library/EmpiricalAutotuning/Autotuner.py +++ b/discopop_library/EmpiricalAutotuning/Autotuner.py @@ -14,6 +14,7 @@ from discopop_library.EmpiricalAutotuning.ArgumentClasses import AutotunerArguments from discopop_library.EmpiricalAutotuning.Classes.CodeConfiguration import CodeConfiguration from discopop_library.EmpiricalAutotuning.Classes.ExecutionResult import ExecutionResult +from discopop_library.EmpiricalAutotuning.Statistics.StatisticsGraph import NodeShape, StatisticsGraph from discopop_library.EmpiricalAutotuning.Types import SUGGESTION_ID from discopop_library.EmpiricalAutotuning.utils import get_applicable_suggestion_ids from discopop_library.HostpotLoader.HotspotLoaderArguments import HotspotLoaderArguments @@ -36,10 +37,17 @@ def get_unique_configuration_id() -> int: def run(arguments: AutotunerArguments) -> None: logger.info("Starting discopop autotuner.") debug_stats: List[Tuple[List[SUGGESTION_ID], float]] = [] + statistics_graph = StatisticsGraph() + statistics_step_num = 0 # get untuned reference result reference_configuration = CodeConfiguration(arguments.project_path, arguments.dot_dp_path) - reference_configuration.execute(timeout=None) + reference_configuration.execute(timeout=None, is_initial=True) + statistics_graph.set_root( + reference_configuration.get_statistics_graph_label(), + color=reference_configuration.get_statistics_graph_color(), + shape=NodeShape.BOX, + ) timeout_after = cast(ExecutionResult, reference_configuration.execution_result).runtime * 2 debug_stats.append(([], cast(ExecutionResult, reference_configuration.execution_result).runtime)) @@ -66,6 +74,21 @@ def run(arguments: AutotunerArguments) -> None: loop_tuples = hotspot_information[hotspot_type] sorted_loop_tuples = sorted(loop_tuples, key=lambda x: x[4], reverse=True) for loop_tuple in sorted_loop_tuples: + loop_str = ( + "" + + str(loop_tuple[0]) + + "@" + + str(loop_tuple[1]) + + " - " + + str(loop_tuple[2]) + + " " + + loop_tuple[3] + + " " + + str(round(loop_tuple[4], 3)) + + "s" + ) + statistics_graph.add_child(loop_str) + statistics_graph.update_current_node(loop_str) # identify all applicable suggestions for this loop logger.debug(str(hotspot_type) + " loop: " + str(loop_tuple)) # create code and execute for all applicable suggestions @@ -80,6 +103,16 @@ def run(arguments: AutotunerArguments) -> None: tmp_config = reference_configuration.create_copy(get_unique_configuration_id) tmp_config.apply_suggestions(arguments, current_config) tmp_config.execute(timeout=timeout_after) + statistics_graph.add_child( + "step " + + str(statistics_step_num) + + "\n" + + str(current_config) + + "\n" + + tmp_config.get_statistics_graph_label(), + shape=NodeShape.BOX, + color=tmp_config.get_statistics_graph_color(), + ) # only consider valid code if ( cast(ExecutionResult, tmp_config.execution_result).result_valid @@ -92,6 +125,16 @@ def run(arguments: AutotunerArguments) -> None: tmp_config.deleteFolder() # add current best configuration for reference / to detect "no suggestions is beneficial" suggestion_effects.append(best_suggestion_configuration) + statistics_graph.add_child( + "step " + + str(statistics_step_num) + + "\n" + + str(best_suggestion_configuration[0]) + + "\n" + + best_suggestion_configuration[1].get_statistics_graph_label(), + shape=NodeShape.BOX, + color=best_suggestion_configuration[1].get_statistics_graph_color(), + ) logger.debug( "Suggestion effects:\n" + str([(str(t[0]), str(t[1].execution_result)) for t in suggestion_effects]) @@ -110,6 +153,26 @@ def run(arguments: AutotunerArguments) -> None: + " stored at " + best_suggestion_configuration[1].root_path ) + statistics_graph.add_child( + "step " + + str(statistics_step_num) + + "\n" + + str(best_suggestion_configuration[0]) + + "\n" + + best_suggestion_configuration[1].get_statistics_graph_label(), + shape=NodeShape.BOX, + color=best_suggestion_configuration[1].get_statistics_graph_color(), + ) + statistics_graph.update_current_node( + "step " + + str(statistics_step_num) + + "\n" + + str(best_suggestion_configuration[0]) + + "\n" + + best_suggestion_configuration[1].get_statistics_graph_label() + ) + statistics_graph.output() + statistics_step_num += 1 # cleanup other configurations (excluding original version) logger.debug("Cleanup:") for _, config in sorted_suggestion_effects: @@ -143,3 +206,6 @@ def run(arguments: AutotunerArguments) -> None: print("Speedup: ", round(speedup, 3)) print("Parallel efficiency: ", round(parallel_efficiency, 3)) print("##############################") + + # output statistics graph + statistics_graph.output() diff --git a/discopop_library/EmpiricalAutotuning/Classes/CodeConfiguration.py b/discopop_library/EmpiricalAutotuning/Classes/CodeConfiguration.py index 8e9bc4354..be7bdcdc4 100644 --- a/discopop_library/EmpiricalAutotuning/Classes/CodeConfiguration.py +++ b/discopop_library/EmpiricalAutotuning/Classes/CodeConfiguration.py @@ -15,6 +15,7 @@ from typing import Callable, List, Optional from discopop_library.EmpiricalAutotuning.ArgumentClasses import AutotunerArguments from discopop_library.EmpiricalAutotuning.Classes.ExecutionResult import ExecutionResult +from discopop_library.EmpiricalAutotuning.Statistics.StatisticsGraph import NodeColor from discopop_library.EmpiricalAutotuning.Types import SUGGESTION_ID from discopop_library.PatchApplicator.PatchApplicatorArguments import PatchApplicatorArguments from discopop_library.PatchApplicator.patch_applicator import run as apply_patches @@ -40,9 +41,11 @@ def __init__(self, root_path: str, config_dot_dp_path: str): def __str__(self) -> str: return self.root_path - def execute(self, timeout: Optional[float]) -> None: + def execute(self, timeout: Optional[float], is_initial: bool = False) -> None: # create timeout string timeout_string = "" if timeout is None else "timeout " + str(timeout) + " " + if is_initial: + timeout_string += "source " # compile code logger.info("Compiling configuration: " + str(self)) compile_result = subprocess.run( @@ -134,3 +137,21 @@ def apply_suggestions(self, arguments: AutotunerArguments, suggestion_ids: List[ sub_logger.debug("Got Exception during call to patch applicator.") os.chdir(save_dir) raise ex + + def get_statistics_graph_label(self) -> str: + res_str = "" + self.root_path + "\n" + if self.execution_result is None: + res_str += "Not executed." + else: + res_str += str(round(self.execution_result.runtime, 3)) + "s" + + return res_str + + def get_statistics_graph_color(self) -> NodeColor: + if self.execution_result is None: + return NodeColor.ORANGE + if self.execution_result.result_valid and self.execution_result.return_code == 0: + return NodeColor.GREEN + if self.execution_result.return_code == 0 and not self.execution_result.result_valid: + return NodeColor.ORANGE + return NodeColor.RED diff --git a/discopop_library/EmpiricalAutotuning/Statistics/StatisticsGraph.py b/discopop_library/EmpiricalAutotuning/Statistics/StatisticsGraph.py new file mode 100644 index 000000000..99aee3077 --- /dev/null +++ b/discopop_library/EmpiricalAutotuning/Statistics/StatisticsGraph.py @@ -0,0 +1,79 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from enum import Enum +import logging +import os +import subprocess +from typing import Any +import networkx as nx # type: ignore + +logger = logging.getLogger("StatisticsGraph") + + +class NodeShape(Enum): + SQUARE = "square" + CIRCLE = "circle" + NONE = "none" + BOX = "box" + + +class NodeColor(Enum): + RED = "red" + WHITE = "white" + GREEN = "green" + ORANGE = "orange" + + +class StatisticsGraph(object): + G: nx.DiGraph + current_node: str = "" + + def __init__(self) -> None: + self.G = nx.DiGraph() + + def dump_to_dot(self) -> None: + filename = "dp_autotuner_statistics.dot" + if os.path.exists(filename): + os.remove(filename) + nx.drawing.nx_pydot.write_dot(self.G, filename) + + def output(self) -> None: + self.dump_to_dot() + self.create_svg_from_dot() + + def set_root(self, label: str, color: NodeColor = NodeColor.WHITE, shape: NodeShape = NodeShape.NONE) -> None: + if shape == NodeShape.NONE: + self.G.add_node(label, color="black", fillcolor=color.value, style="filled") + else: + self.G.add_node(label, color="black", fillcolor=color.value, style="filled", shape=shape.value) + self.current_node = label + + def update_current_node(self, label: str) -> None: + self.current_node = label + + def add_child(self, child: str, color: NodeColor = NodeColor.WHITE, shape: NodeShape = NodeShape.NONE) -> None: + if shape == NodeShape.NONE: + self.G.add_node(child, color="black", fillcolor=color.value, style="filled") + else: + self.G.add_node(child, color="black", fillcolor=color.value, shape=shape.value, style="filled") + self.G.add_edge(self.current_node, child) + + def create_svg_from_dot(self) -> None: + + cmd = "dot -Tsvg dp_autotuner_statistics.dot -o dp_autotuner_statistics.svg" + res = subprocess.run( + cmd, + cwd=os.getcwd(), + executable="/bin/bash", + shell=True, + ) + if res.returncode != 0: + logger.warning("Failed: dot -Tsvg dp_autotuner_statistics.dot -o dp_autotuner_statistics.svg") + else: + logger.info("Updated dp_autotuner_statistics.svg") diff --git a/setup.py b/setup.py index 0f520690a..413ceba19 100644 --- a/setup.py +++ b/setup.py @@ -48,6 +48,7 @@ "sympy_plot_backends", "alive_progress", "filelock", + "pydot", ], extras_require={ "dev": ["mypy", "black", "data-science-types", "pre-commit"], From f0e2673451e4a3c575dd48ec52eab3ee2d223f39 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 23 Jul 2024 15:44:20 +0200 Subject: [PATCH 034/105] cleanup: remove deprecated tools --- DEPRECATED_discopop_profiler/__init__.py | 85 ---- DEPRECATED_discopop_profiler/__main__.py | 91 ---- DEPRECATED_discopop_profiler/utils.py | 52 -- DEPRECATED_discopop_wizard/__init__.py | 0 DEPRECATED_discopop_wizard/__main__.py | 60 --- DEPRECATED_discopop_wizard/assets/__init__.py | 0 .../assets/icons/__init__.py | 0 .../assets/icons/discoPoP_128x128.png | Bin 18077 -> 0 bytes .../assets/profiling_container/Dockerfile | 46 -- .../classes/Arguments.py | 14 - .../classes/CodePreview.py | 109 ---- DEPRECATED_discopop_wizard/classes/Console.py | 65 --- .../classes/ExecutionConfiguration.py | 468 ------------------ DEPRECATED_discopop_wizard/classes/Pragma.py | 27 - .../classes/ProfilingContainer.py | 149 ------ .../classes/Settings.py | 155 ------ .../classes/Suggestion.py | 216 -------- .../classes/TKVarStorage.py | 47 -- .../classes/__init__.py | 0 .../headless/__init__.py | 0 .../headless/headless_execution.py | 65 --- .../screens/__init__.py | 0 .../screens/execution.py | 105 ---- DEPRECATED_discopop_wizard/screens/main.py | 143 ------ .../screens/optimizer/__init__.py | 0 .../screens/optimizer/binding.py | 145 ------ .../screens/settings.py | 180 ------- .../screens/suggestions/__init__.py | 0 .../screens/suggestions/overview.py | 140 ------ DEPRECATED_discopop_wizard/screens/utils.py | 60 --- .../screens/widgets/__init__.py | 0 DEPRECATED_discopop_wizard/utils.py | 65 --- DEPRECATED_discopop_wizard/wizard.py | 187 ------- .../gui/presentation/ChoiceDetails.py | 2 +- .../gui}/widgets/ScrollableText.py | 0 setup.py | 2 - 36 files changed, 1 insertion(+), 2677 deletions(-) delete mode 100644 DEPRECATED_discopop_profiler/__init__.py delete mode 100644 DEPRECATED_discopop_profiler/__main__.py delete mode 100644 DEPRECATED_discopop_profiler/utils.py delete mode 100644 DEPRECATED_discopop_wizard/__init__.py delete mode 100644 DEPRECATED_discopop_wizard/__main__.py delete mode 100644 DEPRECATED_discopop_wizard/assets/__init__.py delete mode 100644 DEPRECATED_discopop_wizard/assets/icons/__init__.py delete mode 100644 DEPRECATED_discopop_wizard/assets/icons/discoPoP_128x128.png delete mode 100644 DEPRECATED_discopop_wizard/assets/profiling_container/Dockerfile delete mode 100644 DEPRECATED_discopop_wizard/classes/Arguments.py delete mode 100644 DEPRECATED_discopop_wizard/classes/CodePreview.py delete mode 100644 DEPRECATED_discopop_wizard/classes/Console.py delete mode 100644 DEPRECATED_discopop_wizard/classes/ExecutionConfiguration.py delete mode 100644 DEPRECATED_discopop_wizard/classes/Pragma.py delete mode 100644 DEPRECATED_discopop_wizard/classes/ProfilingContainer.py delete mode 100644 DEPRECATED_discopop_wizard/classes/Settings.py delete mode 100644 DEPRECATED_discopop_wizard/classes/Suggestion.py delete mode 100644 DEPRECATED_discopop_wizard/classes/TKVarStorage.py delete mode 100644 DEPRECATED_discopop_wizard/classes/__init__.py delete mode 100644 DEPRECATED_discopop_wizard/headless/__init__.py delete mode 100644 DEPRECATED_discopop_wizard/headless/headless_execution.py delete mode 100644 DEPRECATED_discopop_wizard/screens/__init__.py delete mode 100644 DEPRECATED_discopop_wizard/screens/execution.py delete mode 100644 DEPRECATED_discopop_wizard/screens/main.py delete mode 100644 DEPRECATED_discopop_wizard/screens/optimizer/__init__.py delete mode 100644 DEPRECATED_discopop_wizard/screens/optimizer/binding.py delete mode 100644 DEPRECATED_discopop_wizard/screens/settings.py delete mode 100644 DEPRECATED_discopop_wizard/screens/suggestions/__init__.py delete mode 100644 DEPRECATED_discopop_wizard/screens/suggestions/overview.py delete mode 100644 DEPRECATED_discopop_wizard/screens/utils.py delete mode 100644 DEPRECATED_discopop_wizard/screens/widgets/__init__.py delete mode 100644 DEPRECATED_discopop_wizard/utils.py delete mode 100644 DEPRECATED_discopop_wizard/wizard.py rename {DEPRECATED_discopop_wizard/screens => discopop_library/discopop_optimizer/gui}/widgets/ScrollableText.py (100%) diff --git a/DEPRECATED_discopop_profiler/__init__.py b/DEPRECATED_discopop_profiler/__init__.py deleted file mode 100644 index 9a57e9dde..000000000 --- a/DEPRECATED_discopop_profiler/__init__.py +++ /dev/null @@ -1,85 +0,0 @@ -# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) -# -# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany -# -# This software may be modified and distributed under the terms of -# the 3-Clause BSD License. See the LICENSE file in the package base -# directory for details. - -import logging -import os -import re -import subprocess -from contextlib import suppress -from typing import List - -from .utils import recursive_scandir, is_compile, is_link, get_library - - -class DiscopopCpp: - def __init__( - self, - cugeneration: bool, - dpinstrumentation: bool, - dpreduction: bool, - clang_path: str, - ): - self.cugeneration = cugeneration - self.dpinstrumentation = dpinstrumentation - self.dpreduction = dpreduction - self.clang_path = clang_path - - def update_filemapping(self): - cwd = os.getcwd() - with suppress(FileNotFoundError): - # Do not regenerate if FileMapping.txt is still up-to-date. - filemapping_mtime = os.stat("FileMapping.txt").st_mtime - if os.stat(cwd).st_mtime < filemapping_mtime and all( - [not entry.is_dir() or entry.stat().st_mtime < filemapping_mtime for entry in recursive_scandir(cwd)] - ): - return - logging.info("Generating FileMapping.txt.") - with open("FileMapping.txt", "w") as fd: - i = 1 - for entry in sorted(recursive_scandir(cwd), key=lambda e: e.path): - if entry.is_file() and re.match(r"^[^.].+\.(?:c|cc|cpp|h|hpp|ipp)$", entry.name): - print(f"{i}\t{entry.path}", file=fd) - i += 1 - - def wrap_clang_args(self, clang_args: List[str]) -> List[str]: - args = [self.clang_path] - if is_compile(clang_args): - if any([self.cugeneration, self.dpinstrumentation, self.dpreduction]): - self.update_filemapping() - args += ["-g", "-O0", "-fno-discard-value-names"] - if self.cugeneration: - # clang++ -g -O0 -fno-discard-value-names -Xclang -load \ - # -Xclang ${DISCOPOP_INSTALL}/libi/LLVMCUGeneration.so \ - # -mllvm -fm-path -mllvm ./FileMapping.txt -c - args += ["-Xclang", "-load", "-Xclang", get_library("LLVMCUGeneration.so")] - if self.dpinstrumentation: - # clang++ -g -O0 -fno-discard-value-names -Xclang -load \ - # -Xclang ${DISCOPOP_INSTALL}/libi/LLVMDPInstrumentation.so \ - # -mllvm -fm-path -mllvm ./FileMapping.txt -c -o out.o - args += ["-Xclang", "-load", "-Xclang", get_library("LLVMDPInstrumentation.so")] - if self.dpreduction: - # clang++ -g -O0 -fno-discard-value-names -Xclang -load \ - # -Xclang ${DISCOPOP_INSTALL}/libi/LLVMDPReduction.so \ - # -mllvm -fm-path -mllvm ./FileMapping.txt -c -o out.o - args += ["-Xclang", "-load", "-Xclang", get_library("LLVMDPReduction.so")] - args += ["-mllvm", "-fm-path", "-mllvm", "./FileMapping.txt"] - args += clang_args - if is_link(clang_args): - if self.dpinstrumentation or self.dpreduction: - # clang++ out.o -L${DISCOPOP_INSTALL}/rtlib -lDiscoPoP_RT -lpthread - args += [ - f"-L{os.path.dirname(get_library('libDiscoPoP_RT.a'))}", - "-lDiscoPoP_RT", - "-lpthread", - ] - return args - - def invoke(self, clang_args: List[str]) -> subprocess.CompletedProcess: # type: ignore - args = self.wrap_clang_args(clang_args) - logging.info(" ".join(args)) - return subprocess.run(args) diff --git a/DEPRECATED_discopop_profiler/__main__.py b/DEPRECATED_discopop_profiler/__main__.py deleted file mode 100644 index c00ad4690..000000000 --- a/DEPRECATED_discopop_profiler/__main__.py +++ /dev/null @@ -1,91 +0,0 @@ -# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) -# -# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany -# -# This software may be modified and distributed under the terms of -# the 3-Clause BSD License. See the LICENSE file in the package base -# directory for details. - -"""Call clang++ with DiscoPoP LLVM passes.""" - -import argparse -import logging -import shutil - -from discopop_library.global_data.version.utils import get_version -from . import DiscopopCpp - -PROG = "discopop_profiler" - -USAGE = f"""{PROG} [--verbose] [--clang CLANG] - {'':{len(PROG)}} (--CUGeneration | --DPInstrumentation | --DPReduction) - {'':{len(PROG)}} -""" - - -def main(args=None): - parser = argparse.ArgumentParser(prog=PROG, description=__doc__, usage=USAGE, add_help=False) - parser.add_argument("-h", "--help", action="help", help="Show this help message and exit.") - parser.add_argument( - "-V", - "--version", - action="version", - version=f"%(prog)s {get_version()}", - help="Show version number and exit.", - ) - parser.add_argument( - "-v", - "--verbose", - action="store_true", - help="Show additional information such as clang++ invocations.", - ) - parser.add_argument("--clang", help="Path to clang++ executable.") - action = parser.add_mutually_exclusive_group() - action.add_argument( - "--CUGeneration", - "--cugeneration", - action="store_true", - help="Obtain the computational unit (CU) graph of the target application.", - ) - action.add_argument( - "--DPInstrumentation", - "--dpinstrumentation", - action="store_true", - help="Instrument the target application to obtain data dependences.", - ) - action.add_argument( - "--DPReduction", - "--dpreduction", - action="store_true", - help="Instrument the target application to obtain the list of reduction operations.", - ) - parameters, clang_args = parser.parse_known_args(args) - - logging.basicConfig( - format="%(message)s", - level=logging.INFO if parameters.verbose else logging.WARNING, - ) - - if not any([parameters.CUGeneration, parameters.DPInstrumentation, parameters.DPReduction]): - logging.warning( - "Warning: Not using any DiscoPoP LLVM pass (specify either --CUGeneration, " - "--DPInstrumentation or --DPReduction).", - ) - clang_path = parameters.clang or shutil.which("clang++-8") or shutil.which("clang++") - if not clang_path: - raise SystemExit("clang++ executable not found in PATH. Specify --clang PATH/TO/CLANG++.") - if not clang_args: - logging.warning("Warning: No arguments to clang++ were given.") - - clang_proc = DiscopopCpp( - cugeneration=parameters.CUGeneration, - dpinstrumentation=parameters.DPInstrumentation, - dpreduction=parameters.DPReduction, - clang_path=clang_path, - ).invoke(clang_args) - if clang_proc.returncode != 0: - raise SystemExit(clang_proc.returncode) - - -if __name__ == "__main__": - main() diff --git a/DEPRECATED_discopop_profiler/utils.py b/DEPRECATED_discopop_profiler/utils.py deleted file mode 100644 index 5ee7fb686..000000000 --- a/DEPRECATED_discopop_profiler/utils.py +++ /dev/null @@ -1,52 +0,0 @@ -# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) -# -# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany -# -# This software may be modified and distributed under the terms of -# the 3-Clause BSD License. See the LICENSE file in the package base -# directory for details. - -import os -import re -from typing import List, Iterator - - -def get_library(name: str) -> str: - library_dirs: List[str] - if os.getenv("DISCOPOP_INSTALL"): - library_dirs = [ - os.path.expandvars("${DISCOPOP_INSTALL}"), - os.path.expandvars("${DISCOPOP_INSTALL}/libi"), - os.path.expandvars("${DISCOPOP_INSTALL}/rtlib"), - os.path.expandvars("${DISCOPOP_INSTALL}/lib"), - ] - else: - library_dirs = [ - os.path.expanduser("~/.local/lib"), - "/usr/local/lib", - "/usr/lib", - "/lib", - ] - for library_dir in library_dirs: - if os.path.exists(os.path.join(library_dir, name)): - return os.path.join(library_dir, name) - raise SystemExit( - f"File {name} not found. Searched in: {', '.join(library_dirs)}.\n" - f"Build DiscoPoP and set DISCOPOP_INSTALL environment variable." - ) - - -def is_compile(clang_args: List[str]) -> bool: - return "-c" in clang_args or any([re.match(r"^[^-].+\.(?:c|cc|cpp)$", arg) for arg in clang_args]) - - -def is_link(clang_args: List[str]) -> bool: - return "-c" not in clang_args - - -def recursive_scandir(path: str) -> Iterator[os.DirEntry]: # type: ignore - with os.scandir(path) as dir_iter: - for entry in dir_iter: - yield entry - if entry.is_dir(): - yield from recursive_scandir(entry.path) diff --git a/DEPRECATED_discopop_wizard/__init__.py b/DEPRECATED_discopop_wizard/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/DEPRECATED_discopop_wizard/__main__.py b/DEPRECATED_discopop_wizard/__main__.py deleted file mode 100644 index 1e614ce47..000000000 --- a/DEPRECATED_discopop_wizard/__main__.py +++ /dev/null @@ -1,60 +0,0 @@ -# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) -# -# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany -# -# This software may be modified and distributed under the terms of -# the 3-Clause BSD License. See the LICENSE file in the package base -# directory for details. - -import argparse -import os -from os.path import dirname - -from DEPRECATED_discopop_wizard.classes.Arguments import Arguments -from DEPRECATED_discopop_wizard.headless.headless_execution import ( - execute_all_stored_configurations, - execute_tag_filtered_configurations, -) -from DEPRECATED_discopop_wizard.wizard import main as wizard_main - - -def convert_args(namespace_args: argparse.Namespace) -> Arguments: - """Stores args into an Arguments object.""" - return_arg = Arguments() - return_arg.execute_configurations_with_tag = [ - tag for tag in namespace_args.execute_configurations_with_tag.split(",") if len(tag) > 0 - ] - return_arg.execute_all_configurations = namespace_args.execute_all_configurations == "true" - - return return_arg - - -def main(): - parser = argparse.ArgumentParser(description="DiscoPoP Configuration Wizard") - - parser.add_argument( - "--execute_all_configurations", - help="Execute all stored configurations in a headless manner. [true / false]", - ) - parser.add_argument( - "--execute_configurations_with_tag", - default="", - help="Execute all stored configurations in a headless manner which have any of the given tags assigned. [comma-separated list of tags to be executed]", - ) - - args = convert_args(parser.parse_args()) - - if args.execute_all_configurations: - # start headless mode and execute all stored configurations - source_dir = dirname(os.path.abspath(__file__)) # source_dir: discopop/discopop_wizard - execute_all_stored_configurations(args, source_dir) - elif len(args.execute_configurations_with_tag) > 0: - # start headless mode and execute stored configurations with the suitable tags - source_dir = dirname(os.path.abspath(__file__)) # source_dir: discopop/discopop_wizard - execute_tag_filtered_configurations(args, source_dir) - else: - wizard_main(args) - - -if __name__ == "__main__": - main() diff --git a/DEPRECATED_discopop_wizard/assets/__init__.py b/DEPRECATED_discopop_wizard/assets/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/DEPRECATED_discopop_wizard/assets/icons/__init__.py b/DEPRECATED_discopop_wizard/assets/icons/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/DEPRECATED_discopop_wizard/assets/icons/discoPoP_128x128.png b/DEPRECATED_discopop_wizard/assets/icons/discoPoP_128x128.png deleted file mode 100644 index 750685d83867a984dbff99aeb19875aaf44747a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18077 zcmeIYWmH|wvNpPKCqS^^!QFM??(XjH?(XjH7Tg_zh2S0_1a}A|KnQN(PTqI#bM_wh zyW@^C#&`bh1Z$7P6|JNoiGqlS2m*mnq@~1EfcK!+Cp;|hIwW8`2?F6` z`KW2RsTg~bIJr1lSlgMCxOqF7lbCy1TYx}btL3@J?&KXQ;V(lmED(<-s9#-2LRkX) zVrxsJIIkD$mNB)>7_vd6yNnQHKVKfVO#eg%4zF05&~kL-F}#?>PJ0Ga-P|vqD{guO zZU&xb-aSrU9`3=+ss@k#dJqceeR=-)*g0@HchBJ8H|N*O+}Ag^`{UtyE!=<$5ij{D z^SWEfSD*Us21Yt6wW=12h1vM=TJJ?8`ZMDNY0c;5>lQcVYjBJ8=R)8KEm zuw_t4UoS#F4uPP*)W`YoyQhG{*@oms62ZEK(f*OBgb2JqzlF?7zo)~1fK9(djjM)^ zFvr+DL83sv&CV-VwX-jQ-LAC_TTjbJv98bW<~x>_Z+U78cr7jFO)aV}ZB@>z*0;R2 zwz0e2IglCFK6&n990YLm(Q5NYuQo5B_II(^qHD!M#t*1dT)PY7{bCt?MkSpy$}UDXh0 zRvwx(;wF6=IER$>uTneE(LD`fbIu_9`}<50fzRp)%Y#r0sOg4gl8{~fvn!FU|sL}h8bfOO$I z%N*|vZOdH$do1j`rr)$R_3aNHxoWG<75Sbk?j0L%sysq?F3M6Bd9GU*1WRrZe=r#a zqH)~D|L-*4PM^3$TMVojq=x}b?i&e&9s&R4SK0K0zKJP$hQ{-$4% z;guiq_9Wg2>hC-rZ58$vhF82xBPvYH4de|uhhl!Qfu>5)`m?z4zB?sCLX7jO9daI3 zAbwM-4E?nJ$*HDSWBt_a0o)Kpj6qkMtgAGjOLG}#a_B|6iCPSIhEz(nJ4cD>xw~#& z#A=_NjGi_>{?!S)Q@F0IC3Et<6751IrYhgg{-!?9bj0?T6VPWqYgKgLf`mUvy4GGl zhS-pnB;%u}O#MshhWM70SG$)6n_Z?;STzgtJU2N|=%o zNTZgD7AJuUW{-wGkrF`;!Ui^F|G{rt?O84t%V0F(qmCh+yF8e^c^fn#W|deVV;$xm zA-riJ)0Lni$JA3U-xtRzs?F@ZiA?|SNS4YScI@?t8AEqZljh235h7MLsBnhMc%uEi z#qr_C+S)}LWNc~yL5{jO)`Cjo=K0$E!6Q6R{l1l@%}r+S7jM?d2|Q_LhZZ<{1Bj}=ExX1b{@Vn!-+-ugjiLhPAVK<1dC8O@+o z*QDV^Pnbh$HCoWfI=iU3z3FnY6@EM(FI%;IA8xd5UVP%$Oq`w=-)m~LkrGNhWM>c# zd0d$MTdrB*6E0DeLiZVhGM zmzs|wR^j9H5amlAKEcdd&1XIKFyZGgQ0Bo$6Nec`b(NE5WY^U!?#cQealUOXSKI`8 zCufexkos7nnIX&LeuO%)grmKmBoLf!M2}9*NDQ(h^1fDBA{1)yPL`|DM=13Y$UEt)a+qa@`cClNJk+&Jehq^l+7-Xc6xLw0CGJ2iA;j z5WQoS{4sQnpREQe-k-xMfkq$GgE0H0xF>9`g`H8qPwpXZr$DVEjx-Ve8m4v7z-I5k z>X1(Mjril3YNgbz=YzbrjS3%Nl^l%4fM_I2vS7mDXL(#a!mM1O){fuPpcI7qL6M;pJO_Rzyv~?-9ZhA+_NZA*e!-^|{kHi#p~K4P~;Y(y#b1uBqEh#!~w^ z9V-o+hXiF2&LIq%7b%9$)9Z!}>iIW(Tv0*cG3gs&yD*h;o-PHeE}V(%sKlMH%KZVU zGESIX$@4Dx2Cbi@LzakKwRneCbl#gTH+o80qHn_&lHPyhgo%d2*un`j4X5Juz_vpc ziehi5dYec)6f;XprJA;xylggHizkX+X1@q(+d$fpM6P8~LQl&~DFI*WM zq;4P;E+g*srGIcI--*SBf?`v-R6mWTknJVOJ&A<`CRSM#m4;$rdvdj|7^HBLGn*A4ABj<=oQ4M%2LUj&h0Of0n`{x z5uB}m5^Pdcw1Pc)B2obVpbV+F^Ql3PL;Lpr>8@|(|ziI!4S_8i7R4=73l zvY@0D(X)4-`UVmEi>*%b7>BVPN+28KY+{yOh_|otJgO50g=}!fctynX5}lfpLgVoJ ze%*1%jlGY9aYpP&YF70a^5R(|Z@%&xrG~|_qO6jucaOFyHLDY1RBW}-7l28T!vKK| z)o#9PMNI{j%X?8#5Zx?&1yTM$(0rS#4p zQkQd#{aif?)EN~W4U-=Er*xWVhtd|0&SX(rW>&XTEkCPxGc)r=D~XJTMJ;8>!g0i@ ze($#o9RhM%{sh0Stg(cq6E$Rgg2lY^&=pOw4cd=sFyjnK%MDSHll9A2|2!(%ZE)|3t4~rXJED zB-z7T2e$~*5jRooXr$6p2I1z3nEdt-s#G{YFNoqc%S(u?TS#|WsN!v!2#*XhPS$!ss)2&v8S``#` zm1I>t0D)jT`HQwQNaArq>TrmD@Mci)_Hao;8WK@})EwIdoiNk^y3SaaK3puX$1UcC zyWV~w5*L>OU2+zwCjJ9_W2l%+H3hl?H59(!=!lVVf6~t~TYal9ZyD=l95o1FdnO-p6VzmeZV+Y~V8k0-&@3#}E;<63lfmg9F(j7+Vit2A-b#mTa zXuX9DT_gC7E0|y;8Nmz>3P0%0(Oz0veE9Tdiic!h6zeC3rSMh}aqVXT1!@u^Ulk3b zhB{?UC0;G+q+H&KD>^4_MS_~znuDCS9knjl8-MinP=Syxr(!jh{cHkyNG2h*`q~ZZ zCFCHX_nP}vTGl)-WocMg`-q`6AQN|I4K-NxEPeIQDbKeIetTFsR=9DTelUy< z{!w6Rpy<2d$bXX?+S~Ec*neie#sON?r2fv=x}YMUlO~uGBBrRX3wL4<>479+h_#=B zRG{)D)2^ z;|w-`ftl=0ZDB6rw|PMFSj-ctH@n7On_$GW@sq0zz4v9ynM$Cq@l)AgWy^+pQ7xp}|^+;}j~t&G1&I6XCdHw)4xdG;LAM zeM}EIUqNOnH7i*dve4*a3`hM46<#FzvYJgb?T_BB3ao`*0*RsShc&lF6d!eJwJgjXf_c>x<(M1t+VAYt~#KsiO zRyy@5m8UcNM@pr-2^ebJV(&>(CP$a1d--r~p|pDji$8q*ZXMEHVNB)6WcZ?>4G%Re z^+^zNC`q9alWosHhiBqN*|zr)OIv$8YS@O~ksSvUVbKCU9$E;uusp+7de}x6ImczS z6{b2$&7M5pQ4W~^gsYVT8^_Tod?<7Z{Ta3)1M|Z|J9VC3_j^G)T08dsG^s|bKfY|w zd?^WY5=thaMsw>Ub6KL*Q}intZ&CBpEF{El2*qLO-XrAasuwX!$LKcGLz=THyB57G zNMg6QaOWnb35|DH-LaZYsC&>7f73##II}+8?9M}=Jc@h) zW9LB#*(I^uCyc*8fQ+_V5);`JyFzS)-3wtiKuolHs!Tys zwkk?a;}G#AC6tSTF9!j-eYW8AZiyiFuCb@o-_2l7R<2wxq!9O=GH)BikJOp+ko>dN z;SD)qB&0)ap&G_bn5?$?pSjCM<2Y8f!I)c;{0UOK6hi24b!N$R#~$qnYM$MK`NxpK zmP)YqZuqB)ajh&WAGRZPL|V`ke$58st9!Z25~`L~AE8jMKxB}*8@UY>EmF-5pJi)% zGX4mSz;{i#25TwJQAvp@tIs1J8Gj(L-(>Vm*4!_@NuRUHOjwO9q$rL-!x5rJs*<-0 z?y~jU4uET62&>=@_SUScD^w$pFh+r|g*38uM-KFlr6&I_C68Yk;>2p2oqgDL$&JX) z@f6OEm-0Nv{|>dHF$)dcS%(Tond!}G--5g)cg2NTWWq!dPB(?QM7N= zYw#J`yk;q;`}-<-_zA8M2-IY)(28Z|!yMX&Fs00?Wuhb{k`*hTp9JBDc6B%*+K2u< z^rhq)#HF% zStR&_2iz|SvAEoiMU9!B5=r>GDLJ|t?Sb1OU)$}iZ3#H>oD+R+r7NFka%)@2jvq|d zJBH>gKG-rZ1~t&%A%%n`A@r|* zn3^h4eR1x29+kX2M&R(w!kMZnAfsOXMX?XL*x=>WC~+EoQ2wKPHj43Hk%Mu8b!udG z=I7uT0_^ssb0Nj2M`tP_jmNg>_hC)RbAHHCs&=Gj(4UvGW98)8IPyeS+Dl**##f7K zc)EJt2U)5I4gUn=?UEWL`CJ|sd)%h4PA`x|syvuI!9$V4kC9w28PAQq8}m`iqp;A5 zsmjRaG$dOO6;%lFFNu&@G0^S%UislIg%s|9W8%FK3|KD4=~E3!RGGQHG_Scl(hegl za#lOP|EE@7JmP-iC3s^Q-e7rm2gXF3+F42@D-CaW#?r?-xyDu4j5?MC;XeZ1f9k$C zfB31i^dY>AxwY+Uh$tO%^*5M~5JWP;OBGQZeHw@0In;}wmj)55jf$@*5zaQUR#eCv zYP`Yf37a^J)w3rgC~v5VlD~H!X(EmXDV%&Td&Fx{^=9pxC}>4A+sTsMw8 zr-&RS(*jX?jbF^x|JJl>aWzqamwZQXN1`!`O|xrG0tU}b&XWVGLg>ZP$<-!Lgb06d zrLCoMQ4HBSb8+)Is9u#`O---1K6%M2%T4^$TQhM691@B!4H*QZT%M3$M6ds8T^C=a zV(Tqs3d?F6^f#@wG1ebrtd6Sl8LrZoJh+!XQ;t5Ijrmgwz!`tM33%zQ_hzgO_o_|s z0n7e={^BCr+^>Z@_3@cKS@H7Mjtx^wZMPiUq$^LywQmBb$}4{^9p^|C#xGyZ?@Xk< zg9o`-V%oQ^|D&V)qIMvV?dmr6!`04IO*Wj1OX>^l*t((+_)m)4*XHUi=$)`wGRFx&!rT#^k1Mwa^yg$O!ejXY37?ZrjkbSC$)R-`5fzfLKn2-F%^gWiZHUc9hk7&88-AhQ{cv{^t3uS@3?*`fUtcjcf{i10`28YC*^{NTaZI2`9V(BbA#{T0BL0 z^j6+%HHz4R579R! z1U}211f2eoxbAIPY0xpvC&4=5%U*bhK3qj{D4m~syTWh~QiygG@E$VO3^*3>ah&YA zIHf|^5>#L4+kZM}Ri0=5QHxK>t&Iuxg?YADV^){w8~X(*4gPN1w$>l{8`CltDf#=U z{91vP@O}RQEgPZ-UX@Z1oh{dZXs2oInkk9es>RZHe7fkH)v7D*Cx*#VSu+**`QbvG zjf>VBq5;vTZclo z8z(QEaT9R1G{BdI#GyWuwseyk{QY?&1%hD`YwKz(1D(Ca9bCH}$`+_am6fZQZemal zDOMyrS%<+GOePBFiC;*FR!u&&u?a_DWO3S{La~hn+S921AVm|X7R?xaw)m2G^HP~C zq}M;Ou?7M`gjDoKlq{_}tgI2OzEPv(~z5+WEjRFxIiC7>_aO)3U!qhUEO(qa~i zRATA4Gk0ByT75}s?c_$Rhk+Bsu0ds-=>~TqhHS${m8Pba#HQW#m(7umgzg1=?78jq zg@eDwSg1{45n7O;D0uYuHlLe znF*H?K`4o#TAm5O?BuQdX~mCkz_95gvgQQ>`f&gEnfuI@RR8 z_@ncim!iGQvGOEas5pX4YSGZ2cY`n6o*fziChPKu!@&cw_JPPygZf3vEvM(EYYus! zKbG4vj`x%9Mh~f1I8L6NEBA*u+5MXcaW=!H`Z|C3&_Tne~OD-7r{Cb&*l;p1_ZnpfS zTJlOHqK+=+B77VW54sOO?3=XbjuOj}IA!hDs>SFEWX6@)e@+#BV#L?Z2 zpOh51Px8geubYA)_!?%+oDuOiG$|Es@~yNlgl>X?}_ncJD$15I6lQCa?NNJ(jVrT^;j z3W24yz0+U40I>h9rJJ?Ie}naJb9=q>mpcDC5up2j$^Ez1|J41j#y~51d9awHsr&2n zq{aA2U&jZVIhtCVf&cnw%3{pHX2Hq9U}9=w%)oA9V!~j;Wp2vA&BJWW!f9@9%5Bc} zFQTL!T-}TvOwC_K0m2!r0XbY|+$I+6rko6HoUB|7>}G%*9u8Iu1`Z1rGYb}D6CNH; zmVXhU=wc0crLo<=&gxZ^86b+C)0~}$orQ(L#N6D3ft|&enStBXl!Jkjjl;}>+uVf5 zjD`6xQD&xK2}c)uW5Ar&_QsaxOim7#f8BTm94xFP%}>h8_;=I4t|-|VyIBAo_(|og z9o)VCyQ!MBy}7EJ@hh4voSZyt+^k%{J1a9Q=ih4o)my{d#TD?xSD7r#jBJ0)eKiXh zPzC_j_|;DV0sqtzEb3xz?B?jA=ICh0Px>l?guErkbW`7L?^!xjksg<#Vr8yAa|8S^(Ubp@~7>kvg z+l+&Uot1%$69_+c3ocUzV{T4%1};`EV>333SCe!9yL4Aa3pY<=7jt1tKvO^)z=8hK zhJ^YrC~5w^wWpQ&D^ARSaKMbL9BM4=U{)3|3o9Kn3z(Uil<9w8MK(5OGjkrmf6O`A zIT_fwcsLk%c#JIozc%IIW;HisGv?&{_euX>P>}=7!ujti@-e*<*FTNQ$MpX)``-=z zh3Noj{=Nn4_yBv1pY^j|KnZ% zf$M*S!2hW6f4uAe8eE9~y{0pF017=%V8urN5FHMz_Fzq9CB;B5uYX0o6{)}#1SctN zR}cv4?duZ)l#_=GT!eFzmKTRRM0$tv4(*$zGA8h&S4U|vVKuMS)BI!A>f^4nK&Dh` z68N#o5K`1icvM^W@|qetUe$7sr7FL5;@QHE{_+$x+T$|Ma@BX$%PG=%Fa&5=a84SB zw|-g!$Eg#?wdKe*oz-_{2u!oC{I{-#x6p2L!f=HD-!H#x-m~w?ivx3cR|Fe30NRG7 zgut0Ie9qn9@_VKmU~qyZ4?-b@b;q;I~lzhHIR~GnCFhl#HK4E$xX@Q1a1x`z-+kdt| z3*X_^D1p8V@NT~u*a{*~vTfx+!)pz~5Q3Tly&&CrFD=p)Uee%*Cz~`$2^3c7F>?9u zm8;Omlw)Me-86lDui1+i0QZEa1>pcKT*-$Ism5if$$$C+^VI2cQh5E$7(;sRS5R6? z=Hcnt)!*-UawJWT!H$PAG&H0|kG=15UvYF0~4`y~p~r%Md+v-9(n_4WN+$3A0wdlW#hMCtuE`Frv- z845ryH$T64%@Qj!bC6Emhl+|LRrE zs3{AoQOy$9{fcR?1scG98JVQVV#@m`Coxv+GTa0bXwXjqf`X4Lv$*fx3Dc%?KCxZi z^NEUzu5WCh!$ZTvhIZ;PK0G`q)hrR0BKO%M&@XXp)uwFk(r5<%M0h!>mEm8OMf{G5 z2y=6D0}l;ZwqP9*5s_6`XlY^s89MljCih~VI&%^}M2I%s#L+P^J|5-M4s&Q|D0lvh zqBFd$KyXd>P4bDml3%Oi@39wE%}_qa{=F=|mqy+4Pxtpc$x>lJ7eG848=Ds&QLB!< zDkt%)EOxx?{Csl{kBpukUXfxne0==%%}s%kdo_*afckEn)*O(8fY_Zu+%cS&mlp|k zEPAvUx1iwYvD@zL<2zhjtBH*leK&Xa9XGJHme#6l?ffq}M~?bs88 z);tiDAN)D3LCRjHLWQ=00VQ^9u}ami$7eY?xgwRS9FK>7I;b`s2BJi`{;fncS_-^) zjChH0iNrxU*E~YL(0j?Nj(DtRsn&Trzbwj)GC^UEx`?z zaLAsG*9#6Exq#mS_*{79MMg%B{>-oI#$liuAScG)Wr7?wNmip3=O&;`mNH_;^M1Tx zV9Z1+Z+2&lBZ046vKbi}0VW1~;N;|tk|@o~%j2UY*ihey&3HSo6hxvjX|^>y3{z86 zBUY+RL_`F%z4H@z#S>C+i>}a&b;^P*pucc@T)KJ1?pde1x7R-o&$TTS^vpE;bad$r zL=!^f5CH+fwj20$Y$zxwYRo!MV`$-`o*w+n$zfprKD`B6^drB2vjVSJ!)t=*F(D`zjs; z2qj?LluV(ZwKd)Lj*e(CQb3#S3$Lu)+#xeo4*eVdIC?j3f{)&p5rc!myBFL$PFZHG z(gKAqn2=Iy!a+DYcZ9^mZ-G7k)m4#-g{IEVsL6wpii(Qk=5tdsV@F3ORaI4bMn;t? zH7x@J3w!%`IZDxT73*o&k0a9n@%;E<+uq&|fT*XhzjN(#;nRy7Kaw%t7YNg(mjFbc zv2pP6vGvXEEdp%l&$BZD32YB|CDCFfl5`pLc!}uIy%)uH#VWP-=c~Zw_i9yYaR~{( z52x|nz=Qz&^h`{yE-oTfYA0yhED463xphB&=rN80@Bx$h?$+JT6R>rJ1_)>4<&E7s zKYDt~Q=E{j&IJ8kIfycOui;EBHkL(kOSJ&4|m(ar|O$ALK zKYp~U7QL&6ck=XgwXrW5kIT3pqG2PZ=lg z(yJE@N=)`YcFU0>|1>dy2*mcQVRm+QEZ;u@(Ac!;P*PF?rW0k%d>bvMWoUS`yIW#y z{-YrR1Q2y-D3peV1~)ISsfkHQQxgloH3jiMA2pSzF#)>fBYJ}x8S2G1Gcp28MMWil z31ff)L7OhqJ1&YT4zL1Z`0mQ)VRlz z?C2Pso|d01u~8JSQX@?r2Vz~STm=~wl@$z*nYXgbd2?w4PXZ9>irw9F05E2gR_z(` zp-WfB%?m$l3AKx_uPi+_875-#v<2V{a*B$c@V}aTx;r{L430~eY_xTBfIYKtJI=?S zbwbn8`hZXQ`{xG-LjcqYq#bz%?bO!Pi}--?0~dO1S^jAsAD@YitpMHgXWx1afJYWx zaf+3q`~(u0f0*0YAchXksZq5v>~<3tU-#PE>hWOP7ePft&6Z7muy zY?DqMb^3(mJCv!T%j=Z3(^GrEG6DU>kwf!WDID6oa{2&K+SO292y_-+j9+)?;+__8xzD00#?!!bO5-k4#-$nkl+s zGcbfO#aXkF&$s%IH2WX0fH_E!r%-JuYy_I+=5)zu9qGSXu(nTiejk(%Sm@*DoN?N1UCVwMRtSHaq(I=6arQIs-hOX&4Z_ z{A1XTvxDAqo)vPD{S2TyAh`n?9UdJ4Mo|=qPnUtI(~#xNJ;>~Tq5$X#u-r!jCSXj0`PZU0*xfn^gZ|fOXmN z%+1YV0Q&*14^#~K3d=72WmV9XOGkBebpRnv0hk~mA$_xJ{{U@gf9swp)cxGnCsb}NPudhA5mLnbX=FJ;`sWFgY zfkd-2oy*m^ai&NZ`&)WmC|)9T?bHI8>*M2Ncb^7rI#6aRuFWFo?J~O2IGms5e2&D4it*Ava;kD2*Cf|-X7pQB^ou+!zN)v#$S%z7O29%ifj)WC27$|Y&ci~ zX(>55IitO@BMbx-3qUCWM1-%euRC1rN_HKd4V(9e47Ybn44h4p@Yj_!APKxiYW0dJT$<%0PsF< zgnC+1n=SlS0P+W_9e~)M_NfG|wJm-S6MoXE^XDTvnhpHJ22fDskTNl98xR_XFAti4 zYs!?T04jd4lVZ#?1=6+^dyGtZbt3Tl!CpiZ3cyB`xzo*keKSBjqDDgXZ*8%^X065y ztlFg&ML9Vm)@)n?g8i0R0aH)UOf%MTO+){1g$mmVEOmP9aWmHS_4UTa#-Q1wA(JM) zScC8geqsARXPcWu06RxU!eL`$pI}tzN8`jx41N9#El`-a_44P|@A0%FE-sFlhi80h z3K`(AYshpt%7wHeOmU#*{Pg`hHQ>JhZ_XhB)uAUy-hxD@LA3)}@PxqI9FJyo7XK)ZA zSg5FA-AY_~VH6z3m|1i72H?&mOBgRcRb*5YWqM4j2w1ctgR2rHYM^$v&z4`rKym`e z3#h4W+VJW$VpXdAu)}fMQ1$W^B2}vPfB#Ma)||9h=v{g-B+5$3@N>xTsFUZ))ryp_ z{qAZlzm`ziE<$>`yBh-_5))fmTSo)I&6x|VVA}Oh7P})-$H{?w2(XMDCq7A%j3s>C znQKaK`4?!&u`&#Tc7a1ag{fz7*%wVI(B0eya2zoJ&@{loM$BUXMzEm}y#`yHhsz_w zuk_p893oM=bGp{?4Gy+*7E9YeaJwT=(MgxOSY<4U{X2_zkzT!%VI^~8VR40Quui#H z>Ddm?I|%JP`h4hoh0*8_22!e0v%dt21rdIXEQN~u-;+$)IXNXY zHM!q5X=HyyVoqXVOFTMjxs92{_cRmz7RRWfUyIZX`>Ohl-oG;qao=U-2bs_`;34Z!kA-q)~{9A5HNEAWIb`}pG-xQ#stv@#%(4oS4 z3RHOU9}ZS;|NH^ge8K>qoSh{Q|M?Xe7a#vVc|6*YBKou9_tT6${0ct}Rp!y27m};1*AkbZ?dZbpY3$jz4&3QmBmN-h3HW`%TCyu_ZxAGOZ z{7=-UFL=S=YR&hvQ&Zd5KFYQ}JaUF;@r0L2Ol{EP}4YG-fn?C-y!cBv^V>1b~c_JqmkNZT>jbx zlVZVUSUSIGZd|Oiz0u?O^XE@?b6l6YeJ~n4P+kt?aybGSfMhJ{JioEqH9?2Qa+57+ zsmwNK?{;<>GED|%COE*)0qH;{eC#VrPZitm@ZBHeLh{%-(}zCk4h)389v)xkX7YfN z8_?PRa}1EkEi7R36=sj`Ip*t36&hUbfY^GYt90$w#>dByF7LPB{X|45V{$^uy z`YxZVe&V~2U`Wu_)fF=zU)<~wuoeUM9=@%w*G_(t_-La(24sRZo$2*;0$?#9QuPUN zsdzK&+`ilu1YQYI$F<)Vh~aUv(OZjZOk5ub|`>VhC7!YKZKX?KK`|{<* zpb=W`bi~k(m&>43m0I=aBfwaOeityn;yqnQl+;^+J%dt{`m#JQYDf6(hK%@HiYkV1 zk>XiSEIECU(nY3oqFa8}bXUZrM9k?}Jobg)RVQX#rt z&7Y=~)Adc9Z&H3q{){yd)*bNz`FPenNG#?m^dAKL-g)N5_cGB^8%6gOlF)ODAy ze9Ax-W+gB?dl`_1{lB7Vx!5qP=eYXliPLp0?oxjerWNOGKL9j!uxSNLlmex17Zok5alu_86>73qRT z4Bo>l@Mz*wXdHOD(l>3ko=A~2x#(1#<+vF`aICR8*Osb$mm?rgj^lb;K%W-P=|U3w8q>!Vkd+0*+lHPNagk<++WIT>2P znzy;aqT@+N@wa#Ecqw*L_!{5!$cThK>)iP zx>W-$GU+o^^41wIS7{f4j-I|BGCqt;yuo~^) zw+iDg=EjTF=9k+k*WXxhG(FP_SH|vKx;|+i<{V68R{i8(7=j&%V7Ri;xy6@k_?;=5 zKEX%;CGkO0e#{(0L{}0Zow0)$zRc*0*OhCgsV~*E%M(FOeXex}R!!F%ZKTN&Lkb9T zj9`JfoM?2qJt#2h%vqEJamu(sM=SI7qY`}vkDMifeOc#ZW){)0<)U(WO`RT{0Zlii z3#>ithYjpjTA2Aenv4C&THT&N?h>F_b#|ZB`I&UONP(IfQ>9Et8QOl}a@|y@0rB}r zA;iF)%XCPCPXQ`BmoGV9^oymYJ=4&{LF`ZB0`wIDSff>Q3$L-T=EqcD7_p*tRLJ!{ zXh@(^v^x~|Xv$gp;Gl8KYIj=J)#Y!MOHZFkXU6EDwed%(;IP>m;E}l>L`w|hke;U` z1KLZ7AK|sRPng;ESXHSt;Oz-qvSw7Mv2|yRlrg&k$5N#V(B$*x7br|UramQY2rci$ zsM0Ocxx3u9p zwfg43T0@n%c{H=)pyqX3>~m0QrV9#uNKpH&=)13XNdT> zljcgUAI5k|%6Af4bf+gO+^JRjqS?Yhs0g7^f5fCCNu6xezVh18Kwdh_oBqt=d3*l> zE|M0g;FmpXhu^Ho=(E~=W#+dSEecf0Xja+?RpW(sLVbdf>WAh45hF4$(o&d`VN>SA zI=E1L%8e{bXi3YVM{>O=Z1|_q0$HY^Yi5a+dWo)@iEyIsZ5fvo!Z=1c8aUg>eh9$|}d$B8nZ zz@}kU{XKEDuaXT95Qk{Nw%d*a=LTQYNzkFMz#N;-yh9c!k5pW>BMID->p*>7rS^H` zqgb*?)0i??*6lIs@&|#c0@)rJ_F}c!AjI7XzIRyQPuyEE^%+rOvPA69kVOH^u7vxcQh#6 zvcNiRoILB%onC==Oz)6;VzVjGWkHJ=lmx$x&%(;f6V<19nN?pVv-C4if8)t>U|Ll^ zu#_GYLZT+7{1N&O>N<#OU=~7ii57l#3GvF!bH{n@ScA5+v)fjNPly(a`JIpRw|F;y z9i%)hex>M>{FfgmF!Nq60?*ioqS~wnbj`*u{GFO4J!SI7nzh zjHx9_lL8ty>ea#pZr80Z#V5Zgg7r!j0)`NN5t5Gm+mVqDq4af2VZ6JQg~GNkUqI7C zwc3GR!JC~8BaX4R)iS+5B)I(;-Vb=z1|us$Nf?2gpi-A=iiwpVRQ~iTABqaR)Y_bI y-Jz{1s+0M32vyBj^o62=zZd=gyl5uAK#{QwluUr_C4kd7khHjhSiOi*$o~U$3Z2&g diff --git a/DEPRECATED_discopop_wizard/assets/profiling_container/Dockerfile b/DEPRECATED_discopop_wizard/assets/profiling_container/Dockerfile deleted file mode 100644 index 06089aac3..000000000 --- a/DEPRECATED_discopop_wizard/assets/profiling_container/Dockerfile +++ /dev/null @@ -1,46 +0,0 @@ -# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) -# -# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany -# -# This software may be modified and distributed under the terms of -# the 3-Clause BSD License. See the LICENSE file in the package base -# directory for details. - -FROM ubuntu:22.04 - -ENV TZ=Europe/Berlin -RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone - -RUN apt-get update -RUN apt-get install -y git cmake gcc libclang-11-dev clang-11 llvm-11 clang-tools-11 python3 python3-pip python3-tk wget file - -# clone DiscoPoP -RUN git clone https://github.com/discopop-project/discopop.git -WORKDIR /discopop - -# install DiscoPoP -RUN mkdir build -WORKDIR /discopop/build -RUN cmake .. -RUN make -WORKDIR /discopop - -# install GO -WORKDIR / -RUN mkdir software -WORKDIR /software -RUN wget https://dl.google.com/go/go1.16.15.linux-amd64.tar.gz -RUN tar -xvf * -RUN rm *.tar.gz -RUN ln -s /software/go/bin/go /usr/bin/go - -# install GLLVM -WORKDIR / -RUN GOPATH=/software/go/bin GO111MODULE=off go get github.com/SRI-CSL/gllvm/cmd/... -WORKDIR /software/go/bin -RUN mv bin/* . -RUN mv src/* ../src - -# install python dependencies and modules -WORKDIR /discopop -RUN pip install . diff --git a/DEPRECATED_discopop_wizard/classes/Arguments.py b/DEPRECATED_discopop_wizard/classes/Arguments.py deleted file mode 100644 index bffc171ee..000000000 --- a/DEPRECATED_discopop_wizard/classes/Arguments.py +++ /dev/null @@ -1,14 +0,0 @@ -# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) -# -# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany -# -# This software may be modified and distributed under the terms of -# the 3-Clause BSD License. See the LICENSE file in the package base -# directory for details. -from typing import List - - -class Arguments(object): - no_gui: bool = False - execute_all_configurations: bool = False - execute_configurations_with_tag: List[str] = [] diff --git a/DEPRECATED_discopop_wizard/classes/CodePreview.py b/DEPRECATED_discopop_wizard/classes/CodePreview.py deleted file mode 100644 index f2bbbd610..000000000 --- a/DEPRECATED_discopop_wizard/classes/CodePreview.py +++ /dev/null @@ -1,109 +0,0 @@ -# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) -# -# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany -# -# This software may be modified and distributed under the terms of -# the 3-Clause BSD License. See the LICENSE file in the package base -# directory for details. - -import tkinter as tk -from pathlib import Path -from typing import Optional, List, cast - -from discopop_library.CodeGenerator.classes.ContentBuffer import ContentBuffer -from discopop_library.CodeGenerator.classes.Line import Line - - -class CodePreviewLine(Line): - highlight_color: Optional[str] - - def __init__(self, parent_line_num: int, line_num=None, content=""): - super().__init__(parent_line_num, line_num, content) - self.highlight_color = None - - def display(self, wizard, parent_element: tk.Text, line_idx: int, max_line_num: int): - if not self.content.endswith("\n"): - self.content += "\n" - - # assemble line_num_str if requested - line_num_str = "" - if wizard.settings.code_preview_show_line_numbers == 1: - line_num_str = str(self.line_num) if self.line_num is not None else "" - while len(line_num_str) < len(str(max_line_num)): - line_num_str += " " - line_num_str += " " # padding - - # assemble line for display - line = "" - line += line_num_str - line += self.content - - parent_element.insert(tk.END, line) - - # highlight inserted pragmas - if self.line_num is None: - # todo generate background colors - background_color = "#e5f2b3" if line_idx % 2 == 0 else "#a4ed9a" - if self.owns_region is not None: - # highlight entire line if a new region is created - self.__highlight(parent_element, line_idx, 0, len(line), background_color) - else: - # highlight pragma only - self.__highlight( - parent_element, - line_idx, - len(line) - len(self.content), - len(line), - background_color, - ) - - def __highlight( - self, - parent_element: tk.Text, - line_idx: int, - start_position: int, - end_position: int, - color: str, - ): - """highlights the given section of the line in the given color""" - start_position_str = str(line_idx) + "." + str(start_position) - end_position_str = str(line_idx) + "." + str(end_position) - parent_element.tag_add( - color + ":" + start_position_str + "-" + end_position_str, - start_position_str, - end_position_str, - ) - parent_element.tag_config( - color + ":" + start_position_str + "-" + end_position_str, - background=color, - foreground="black", - ) - - -class CodePreviewContentBuffer(ContentBuffer): - max_line_num: int # used to determine width of padding - file_id: int - next_free_region_id = 0 - lines: List[Line] - - def __init__(self, wizard, file_id: int, source_code_path: Path, tab_width: int = 4): - super().__init__(file_id, source_code_path, tab_width, line_type=CodePreviewLine) - self.wizard = wizard - - def show_in(self, parent_element: tk.Text): - """Displays the contents of the CodePreview object in the supplied parent_element.""" - for line_idx, line in enumerate(self.lines): - # offset line_id to account for start with 1 - offset_line_id = line_idx + 1 - cast(CodePreviewLine, line).display(self.wizard, parent_element, offset_line_id, self.max_line_num) - - def jump_to_first_modification(self, parent_element: tk.Text): - """Jumps to the location of the first modified source code location.""" - first_location = "" - for idx, line in enumerate(self.lines): - if line.line_num is None: - first_location = "" + str(idx) + ".0" - break - if first_location == "": - first_location = "1.0" - parent_element.see(first_location) diff --git a/DEPRECATED_discopop_wizard/classes/Console.py b/DEPRECATED_discopop_wizard/classes/Console.py deleted file mode 100644 index f6fd37a1e..000000000 --- a/DEPRECATED_discopop_wizard/classes/Console.py +++ /dev/null @@ -1,65 +0,0 @@ -# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) -# -# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany -# -# This software may be modified and distributed under the terms of -# the 3-Clause BSD License. See the LICENSE file in the package base -# directory for details. -import tkinter as tk -from tkinter import ttk - - -class Console(object): - parent_frame: tk.Frame - progress_bar: ttk.Progressbar - log_screen: tk.Text - - def __init__(self, parent_frame: tk.Frame): - self.parent_frame = tk.Frame(parent_frame, bg="red") - self.parent_frame.grid(row=1, column=1, sticky="nsew") - self.__show_console() - - def print(self, msg: str): - if not msg.endswith("\n"): - msg = msg + "\n" - self.log_screen.config(state=tk.NORMAL) - self.log_screen.insert(tk.END, msg) - self.log_screen.see(tk.END) - self.log_screen.update() - self.log_screen.config(state=tk.DISABLED) - - def clear(self): - raise NotImplementedError("TODO") - - def start_progress(self): - self.progress_bar.start(20) - self.progress_bar.update() - - def stop_progress(self): - self.progress_bar.stop() - self.progress_bar.update() - - def __show_console(self): - for c in self.parent_frame.winfo_children(): - c.destroy() - # configure parent_frame - self.parent_frame.rowconfigure(0, weight=1) - self.parent_frame.columnconfigure(0, weight=1) - # self.parent_frame.rowconfigure(2, weight=1) - - # create content frame and scroll bars - self.log_screen = tk.Text(self.parent_frame, wrap=tk.NONE, height=8) - self.log_screen.grid(row=0, column=0, sticky="nsew") - self.log_screen.config(state=tk.DISABLED) - - # create a Scrollbar and associate it with the content frame - y_scrollbar = ttk.Scrollbar(self.parent_frame, command=self.log_screen.yview) - y_scrollbar.grid(row=0, column=1, sticky="nsew") - self.log_screen["yscrollcommand"] = y_scrollbar.set - x_scrollbar = ttk.Scrollbar(self.parent_frame, orient="horizontal", command=self.log_screen.xview) - x_scrollbar.grid(row=1, column=0, columnspan=2, sticky="nsew") - self.log_screen["xscrollcommand"] = x_scrollbar.set - - # create progress bar - # self.progress_bar = ttk.Progressbar(self.parent_frame, orient=tk.HORIZONTAL, mode="determinate") - # self.progress_bar.grid(row=2, column=0, columnspan=2, sticky="nsew") diff --git a/DEPRECATED_discopop_wizard/classes/ExecutionConfiguration.py b/DEPRECATED_discopop_wizard/classes/ExecutionConfiguration.py deleted file mode 100644 index 2018519fc..000000000 --- a/DEPRECATED_discopop_wizard/classes/ExecutionConfiguration.py +++ /dev/null @@ -1,468 +0,0 @@ -# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) -# -# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany -# -# This software may be modified and distributed under the terms of -# the 3-Clause BSD License. See the LICENSE file in the package base -# directory for details. - -import os -import random -import string -import subprocess -import tkinter as tk -from json import JSONDecodeError -from tkinter import filedialog -from typing import TextIO, List, Dict, Tuple, Any - -import jsons # type:ignore - -from DEPRECATED_discopop_wizard.screens.execution import ExecutionView -from DEPRECATED_discopop_wizard.screens.optimizer.binding import create_optimizer_screen -from DEPRECATED_discopop_wizard.screens.suggestions.overview import ( - show_suggestions_overview_screen, - get_suggestion_objects, -) -from DEPRECATED_discopop_wizard.screens.utils import create_tool_tip - - -class ExecutionConfiguration(object): - button: tk.Button - value_dict: Dict[str, Any] - - def __init__(self, wizard): - self.value_dict = { - "label": "", - "description": "", - "executable_name": "", - "executable_arguments": "", - "make_flags": "", - "project_path": "", - "linker_flags": "", - "make_target": "", - "memory_profiling_skip_function_parameters": 0, - "notes": "", - "working_copy_path": "", - "tags": "", - "explorer_flags": "--json=patterns.json --dump-detection-result", - } - self.value_dict["id"] = "".join(random.choices(string.ascii_uppercase + string.digits, k=8)) - self.wizard = wizard - - # self.__extract_values_from_help_string() - - def __extract_values_from_help_string(self): - """Read help strings of: - - DiscoPoP Explorer - - runDiscoPoP script - in order to automatically determine the required and optional arguments""" - targets: List[Tuple[str, str]] = [ # [(name, executable)] - ("rundiscopop", self.wizard.settings.discopop_build_dir + "/scripts/runDiscoPoP"), - ("explorer", "discopop_explorer"), - ] - for target_name, target_executable in targets: - # get help string - tmp = subprocess.run([target_executable, "--help"], stdout=subprocess.PIPE) - help_string = tmp.stdout.decode("utf-8") - for line in help_string.split("\n"): - line = line.replace("\t", " ") - while " " in line: - line = line.replace(" ", " ") - if line.startswith(" "): - line = line[1:] - if not line.startswith("* --"): - continue - line = line[4:] # cut off '* --' - # extract name and type - name_cutoff_index = len(line) - if " " in line: - name_cutoff_index = min(name_cutoff_index, line.index(" ")) - if "=" in line: - name_cutoff_index = min(name_cutoff_index, line.index("=")) - value_name = line[:name_cutoff_index] - if value_name == "help": - continue - line = line[name_cutoff_index:] - # extract type if present - value_type = "bool" - if "<" in line and ">" in line: - left_index = line.index("<") + 1 - right_index = line.index(">") - value_type = line[left_index:right_index] - # add value to dictionaries - self.value_dict[target_name + "_" + value_name] = "" - # self.type_dict[target_name + "_" + value_name] = value_type - - def get_as_button(self, wizard, main_screen_obj, parent_frame: tk.Frame, all_buttons: List[tk.Button]) -> tk.Button: - button = tk.Button(parent_frame, text=self.value_dict["label"]) - button.config( - command=lambda: self.highlight_and_update_notebook_screens(wizard, main_screen_obj, button, all_buttons) - ) - self.button = button - return button - - def init_from_json(self, json_file: TextIO): - json_str = "" - for line in json_file.readlines(): - json_str += line - self.value_dict = {**self.value_dict, **jsons.loads(json_str)} # merge both dictionaries - - def get_values_as_json_string(self): - """returns a representation of the settings which will be stored in a configuration file.""" - return jsons.dumps(self.value_dict) - - def highlight_and_update_notebook_screens( - self, wizard, main_screen_obj, pressed_button: tk.Button, all_buttons: List[tk.Button] - ): - # remove previous highlights - for configuration_button in all_buttons: - configuration_button.configure(state=tk.NORMAL) - - # highlight pressed configuration button - pressed_button.configure(state=tk.DISABLED) - - # update details screen of pressed configuration button - self.show_details_screen(wizard, main_screen_obj) - - # update results screen of pressed configuration button and set results tab state based on result existence - main_screen_obj.notebook.tab(main_screen_obj.results_frame, state=self.__button_state_from_result_existence()) - main_screen_obj.notebook.tab(main_screen_obj.optimizer_frame, state=self.__button_state_from_result_existence()) - - if self.__button_state_from_result_existence() == "normal": - show_suggestions_overview_screen(wizard, main_screen_obj.results_frame, self) - if self.__button_state_from_result_existence() == "normal": - create_optimizer_screen(wizard, main_screen_obj.optimizer_frame, self) - - def show_details_screen(self, wizard, main_screen_obj): - # delete previous frame contents - for c in main_screen_obj.details_frame.winfo_children(): - c.destroy() - - frame = tk.Frame(main_screen_obj.details_frame) - frame.grid(row=1, column=2) - - canvas = tk.Canvas(frame) - canvas.grid(row=1) - - # show labels - tk.Label(canvas, text="Label:", justify=tk.RIGHT, anchor="e", font=wizard.style_font_bold_small).grid( - row=1, column=1, sticky="ew" - ) - tk.Label(canvas, text="Description", justify=tk.RIGHT, anchor="e").grid(row=2, column=1, sticky="ew") - tk.Label( - canvas, - text="Executable name:", - justify=tk.RIGHT, - anchor="e", - font=wizard.style_font_bold_small, - ).grid(row=3, column=1, sticky="ew") - tk.Label(canvas, text="Executable arguments:", justify=tk.RIGHT, anchor="e").grid(row=4, column=1, sticky="ew") - tk.Label(canvas, text="Make flags:", justify=tk.RIGHT, anchor="e").grid(row=5, column=1, sticky="ew") - tk.Label( - canvas, - text="Project path:", - justify=tk.RIGHT, - anchor="e", - font=wizard.style_font_bold_small, - ).grid(row=6, column=1, sticky="ew") - tk.Label(canvas, text="Project linker flags:", justify=tk.RIGHT, anchor="e").grid(row=7, column=1, sticky="ew") - tk.Label(canvas, text="Make target:", justify=tk.RIGHT, anchor="e").grid(row=8, column=1, sticky="ew") - tk.Label( - canvas, - text="Memory Profiling:", - justify=tk.RIGHT, - anchor="e", - font=wizard.style_font_bold_small, - ).grid(row=9, column=1, sticky="ew") - tk.Label(canvas, text="Skip function params:", justify=tk.RIGHT, anchor="e").grid(row=10, column=1, sticky="ew") - tk.Label( - canvas, - text="Additional:", - justify=tk.RIGHT, - anchor="e", - font=wizard.style_font_bold_small, - ).grid(row=11, column=1, sticky="ew") - tk.Label(canvas, text="Tags:", justify=tk.RIGHT, anchor="e").grid(row=12, column=1, sticky="ew") - tk.Label(canvas, text="Notes:", justify=tk.RIGHT, anchor="e").grid(row=13, column=1, sticky="ew") - - # show input fields - label = tk.Entry(canvas) - label.grid(row=1, column=2, sticky="ew") - label.insert(tk.END, self.value_dict["label"]) - create_tool_tip(label, "Name of the configuration. Used to distinguish configurations in the main menu.") - - description = tk.Entry(canvas) - description.grid(row=2, column=2, sticky="ew") - description.insert(tk.END, self.value_dict["description"]) - - executable_name = tk.Entry(canvas) - executable_name.insert(tk.END, self.value_dict["executable_name"]) - executable_name.grid(row=3, column=2, sticky="ew") - create_tool_tip( - executable_name, - "Name of the executable which is created when building the target project. The name will be " - "used to execute the configuration.", - ) - - executable_args = tk.Entry(canvas) - executable_args.grid(row=4, column=2, sticky="ew") - executable_args.insert(tk.END, self.value_dict["executable_arguments"]) - create_tool_tip( - executable_args, - "Specify arguments which shall be forwarded to the call of the created executable for the " "profiling.", - ) - - make_flags = tk.Entry(canvas) - make_flags.grid(row=5, column=2, sticky="ew") - make_flags.insert(tk.END, str(self.value_dict["make_flags"])) - create_tool_tip( - make_flags, - "Specified flags will be forwarded to Make during the build of the target project.", - ) - - project_path = tk.Entry(canvas) - project_path.grid(row=6, column=2, sticky="ew") - project_path.insert(tk.END, self.value_dict["project_path"]) - create_tool_tip(project_path, "Path to the project which shall be analyzed for potential parallelism.") - - def overwrite_with_selection(target: tk.Entry): - prompt_result = tk.filedialog.askdirectory() - if len(prompt_result) != 0: - target.delete(0, tk.END) - target.insert(0, prompt_result) - - project_path_selector = tk.Button(canvas, text="Select", command=lambda: overwrite_with_selection(project_path)) - project_path_selector.grid(row=6, column=3) - - project_linker_flags = tk.Entry(canvas) - project_linker_flags.grid(row=7, column=2, sticky="ew") - project_linker_flags.insert(tk.END, self.value_dict["linker_flags"]) - create_tool_tip( - project_linker_flags, - "Linker flags which need to be passed to the build system in order to create a valid " "executable.", - ) - - make_target = tk.Entry(canvas) - make_target.grid(row=8, column=2, sticky="ew") - make_target.insert(tk.END, self.value_dict["make_target"]) - create_tool_tip(make_target, "Space-separated list of make targets to be created.") - - mpsfp_var = tk.IntVar() - mpsfp_var.set(self.value_dict["memory_profiling_skip_function_parameters"]) - memory_profiling_skip_function_parameters = tk.Checkbutton(canvas, onvalue=1, offvalue=0, variable=mpsfp_var) - memory_profiling_skip_function_parameters.grid(row=10, column=2, sticky="w") - create_tool_tip( - memory_profiling_skip_function_parameters, - "Disables the memory profiling for function arguments.\n\n" - "Depending on the application, this may lead to significant profiling runtime\n" - "improvements, but the correctness of the results can not be guaranteed anymore!\n" - "Use this mode with caution, and be aware of potential issues!", - ) - - tags = tk.Entry(canvas) - tags.grid(row=12, column=2, sticky="ew") - tags.insert(tk.END, self.value_dict["tags"]) - create_tool_tip(tags, "Space-separated list of tags for identification.") - - additional_notes = tk.Text(canvas, height=10) - additional_notes.grid(row=13, column=2, sticky="ew") - additional_notes.insert(tk.END, self.value_dict["notes"]) - create_tool_tip(additional_notes, "Can be used to store notes regarding the configuration.") - - # show buttons - button_canvas = tk.Canvas(frame) - button_canvas.grid(row=2) - # Create "Save" button - save_button = tk.Button( - button_canvas, - text="Save", - command=lambda: self.save_changes( - wizard, - main_screen_obj, - label, - description, - executable_name, - executable_args, - make_flags, - project_path, - project_linker_flags, - make_target, - mpsfp_var, - tags, - additional_notes, - ), - ) - save_button.grid(row=1, column=1) - - # Create "Delete" button - delete_button = tk.Button( - button_canvas, - text="Delete", - command=lambda: self.delete_configuration(wizard, main_screen_obj, frame), - ) - delete_button.grid(row=1, column=2) - - # Create "Open Folder" button - if os.path.exists(os.path.join(project_path.get(), ".discopop")): - target_path = os.path.join(project_path.get(), ".discopop") - else: - target_path = project_path.get() - open_project_folder_button = tk.Button( - button_canvas, - text="Open Folder", - command=lambda: os.system( - "xdg-open " - + str( - os.path.join(project_path.get(), ".discopop") - if os.path.exists(os.path.join(project_path.get(), ".discopop")) - else project_path.get() - ) - ), - ) - open_project_folder_button.grid(row=1, column=3) - - # Create "Execute" button - execute_button = tk.Button( - button_canvas, - text="Execute", - command=lambda: self.execute_configuration( - wizard, - main_screen_obj, - label, - description, - executable_name, - executable_args, - make_flags, - project_path, - project_linker_flags, - make_target, - mpsfp_var, - tags, - additional_notes, - ), - ) - execute_button.grid(row=1, column=4) - - def __button_state_from_result_existence(self) -> str: - # check if suggestions can be loaded. If so, enable the button. - # Else, disable it. - try: - suggestions = get_suggestion_objects(self.wizard, self) - except FileNotFoundError: - return "disabled" - except JSONDecodeError: - return "disabled" - return "normal" - - def save_changes( - self, - wizard, - main_screen_obj, - label, - description, - executable_name, - executable_args, - make_flags, - project_path, - project_linker_flags, - make_target, - memory_profiling_skip_function_parameters, - tags, - additional_notes, - rebuild_configurations_frame=True, - ): - # update execution configuration - self.value_dict["label"] = label.get() - self.value_dict["description"] = description.get() - self.value_dict["executable_name"] = executable_name.get() - self.value_dict["executable_arguments"] = executable_args.get() - self.value_dict["make_flags"] = make_flags.get() - self.value_dict["project_path"] = project_path.get() - self.value_dict["working_copy_path"] = self.value_dict["project_path"] + "/.discopop" - self.value_dict["linker_flags"] = project_linker_flags.get() - self.value_dict["make_target"] = make_target.get() - self.value_dict["memory_profiling_skip_function_parameters"] = memory_profiling_skip_function_parameters.get() - self.value_dict["tags"] = tags.get() - self.value_dict["notes"] = additional_notes.get("1.0", tk.END) - - # construct config path - config_path = os.path.join( - wizard.config_dir, - "execution_configurations", - str(self.value_dict["id"]) + "_" + self.value_dict["label"] + ".json", - ) - # remove old config if present - if os.path.exists(config_path): - os.remove(config_path) - # write config to file - with open(config_path, "w+") as f: - f.write(self.get_values_as_json_string()) - - if rebuild_configurations_frame: # used to prevent de-selecting button on execution - main_screen_obj.build_configurations_frame(wizard) - print("Saved configuration") - self.wizard.console.print("Saved configuration") - - def delete_configuration(self, wizard, main_screen_obj, details_frame: tk.Frame): - # delete configuration file if it exists - config_path = os.path.join( - wizard.config_dir, - "execution_configurations", - str(self.value_dict["id"]) + "_" + self.value_dict["label"] + ".json", - ) - if os.path.exists(config_path): - os.remove(config_path) - - main_screen_obj.build_configurations_frame(wizard) - # remove details view - for c in details_frame.winfo_children(): - c.destroy() - - def execute_configuration( - self, - wizard, - main_screen_obj, - label, - description, - executable_name, - executable_args, - make_flags, - project_path, - project_linker_flags, - make_target, - memory_profiling_skip_function_parameters, - tags, - additional_notes, - ): - # save changes - self.save_changes( - wizard, - main_screen_obj, - label, - description, - executable_name, - executable_args, - make_flags, - project_path, - project_linker_flags, - make_target, - memory_profiling_skip_function_parameters, - tags, - additional_notes, - rebuild_configurations_frame=False, - ) - - # create execution view and update results frame - ExecutionView(self, wizard, main_screen_obj.results_frame) - # set results tab state based on result existence - main_screen_obj.notebook.tab(main_screen_obj.results_frame, state=self.__button_state_from_result_existence()) - main_screen_obj.notebook.tab(main_screen_obj.optimizer_frame, state=self.__button_state_from_result_existence()) - - # show results tab - main_screen_obj.notebook.select(main_screen_obj.results_frame) - # initialize optimizer tab - create_optimizer_screen(wizard, main_screen_obj.optimizer_frame, self) - - def get_tags(self) -> List[str]: - """Returns a list of strings which represents the tags assigned to the configuration.""" - return [tag for tag in self.value_dict["tags"].split(" ") if len(tag) != 0] diff --git a/DEPRECATED_discopop_wizard/classes/Pragma.py b/DEPRECATED_discopop_wizard/classes/Pragma.py deleted file mode 100644 index 9b1503a5a..000000000 --- a/DEPRECATED_discopop_wizard/classes/Pragma.py +++ /dev/null @@ -1,27 +0,0 @@ -# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) -# -# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany -# -# This software may be modified and distributed under the terms of -# the 3-Clause BSD License. See the LICENSE file in the package base -# directory for details. - -from enum import IntEnum -from typing import Optional, List, Any - - -class PragmaPosition(IntEnum): - BEFORE_START = 0 - AFTER_START = 1 - BEFORE_END = 2 - AFTER_END = 3 - - -class Pragma(object): - pragma_str: str = "" - file_id: Optional[int] = None - start_line: Optional[int] = None - end_line: Optional[int] = None - pragma_position: PragmaPosition = PragmaPosition.BEFORE_START - parent_cu_id: str = "" - children: List[Any] = [] diff --git a/DEPRECATED_discopop_wizard/classes/ProfilingContainer.py b/DEPRECATED_discopop_wizard/classes/ProfilingContainer.py deleted file mode 100644 index bb9b1ef19..000000000 --- a/DEPRECATED_discopop_wizard/classes/ProfilingContainer.py +++ /dev/null @@ -1,149 +0,0 @@ -# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) -# -# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany -# -# This software may be modified and distributed under the terms of -# the 3-Clause BSD License. See the LICENSE file in the package base -# directory for details. - -import glob -import os -import pathlib -import shutil -import subprocess -import tkinter - - -class ProfilingContainer(object): - def __init__(self, wizard): - self.wizard = wizard - self.start() - - def start(self): - docker_context_path = os.path.join( - pathlib.Path(__file__).parent.resolve(), "..", "assets", "profiling_container" - ) - self.__execute_command("docker kill discopop_container") - self.__execute_command("docker rm discopop_container") - exit_code = self.__execute_command("docker build -t discopop_container " + docker_context_path) - assert exit_code == 0 - exit_code = self.__execute_command("docker run --name discopop_container -d -t discopop_container") - assert exit_code == 0 - - def stop(self): - print("Stopping DiscoPoP profiling container...") - self.__execute_command("docker kill discopop_container") - print("Done.") - - def remove_project_folder(self): - self.__execute_command("docker exec -it discopop_container rm -rvf /project") - - def remove_previous_results(self, target_folder): - files = glob.glob(target_folder + "/*") - for f in files: - if os.path.exists(f): - if os.path.isfile(f): - os.remove(f) - else: - shutil.rmtree(f) - - def copy_project_folder_to_container(self, project_path: str): - self.remove_project_folder() - self.__execute_command("docker cp " + project_path + " discopop_container:/project") - - def copy_results_from_container(self, target_path: str, execution_view): - result_files = [ - "FileMapping.txt", - "Data.xml", - "loop_counter_output.txt", - "reduction.txt", - execution_view.execution_configuration.value_dict["executable_name"] + "_dp_dep.txt", - execution_view.execution_configuration.value_dict["executable_name"] + "_dp.ll", - "patterns.txt", - "patterns.json", - ] - for file in result_files: - exit_code = self.__execute_command( - "docker cp discopop_container:/project/.discopop/" + file + " " + target_path - ) - assert exit_code == 0 - - def analyze_project(self, execution_view): - # copy project folder to container. Note: mounting would be nicer but requires restarting the container. - # might be a nicer solution in the long run, especially for larger projects - self.copy_project_folder_to_container(execution_view.execution_configuration.value_dict["project_path"]) - - # settings - command = "/discopop/build/scripts/runDiscoPoP " - command += "--llvm-clang clang-11 " - command += "--llvm-clang++ clang++-11 " - command += "--llvm-ar llvm-ar-11 " - command += "--llvm-link llvm-link-11 " - command += "--llvm-dis llvm-dis-11 " - command += "--llvm-opt opt-11 " - command += "--llvm-llc llc-11 " - command += "--gllvm /software/go/bin " - # execution configuration - command += "--project /project " - command += '--linker-flags "' + execution_view.execution_configuration.value_dict["linker_flags"] + '" ' - command += '--executable-name "' + execution_view.execution_configuration.value_dict["executable_name"] + '" ' - command += ( - '--executable-arguments "' - + execution_view.execution_configuration.value_dict["executable_arguments"] - + '" ' - ) - command += '--make-flags "' + execution_view.execution_configuration.value_dict["make_flags"] + '" ' - command += '--make-target "' + execution_view.execution_configuration.value_dict["make_target"] + '" ' - command += '--explorer-flags "' + execution_view.execution_configuration.value_dict["explorer_flags"] + '" ' - - self.__execute_command("docker exec -it discopop_container " + command) - - # copy results from container into working copy path - if not os.path.exists(execution_view.execution_configuration.value_dict["working_copy_path"]): - os.mkdir(execution_view.execution_configuration.value_dict["working_copy_path"]) - - # remove previous results - self.remove_previous_results(execution_view.execution_configuration.value_dict["working_copy_path"]) - - # copy results from container - self.copy_results_from_container( - execution_view.execution_configuration.value_dict["working_copy_path"], execution_view - ) - - # correct paths in generated FileMapping.txt - self.__correct_file_mapping_paths(execution_view) - - def __correct_file_mapping_paths(self, execution_view): - file_mapping_path = os.path.join( - execution_view.execution_configuration.value_dict["working_copy_path"], - "FileMapping.txt", - ) - with open(file_mapping_path, "r") as file: - contents = file.read() - contents = contents.replace( - "/project/.discopop", execution_view.execution_configuration.value_dict["project_path"] - ) - with open(file_mapping_path, "w") as file: - file.write(contents) - - def __execute_command(self, command: str) -> int: - with subprocess.Popen(command, stdout=subprocess.PIPE, bufsize=1, universal_newlines=True, shell=True) as p: - if p.stdout is None: - print("executing command was not successfull") - else: - for line in p.stdout: - line = line.replace("\n", "") - print(line) - try: - self.wizard.console.print(line) - except tkinter.TclError: - # happens when container is still shutting down but interface already closed. - pass - if p.returncode != 0: - print("An error occurred during the execution!") # Error message - self.wizard.console.print("An error occurred during the execution!") - for line in str(subprocess.CalledProcessError(p.returncode, p.args)).split("\n"): - line = line.replace("\n", "") - print(line) - self.wizard.console.print(line) - return p.returncode diff --git a/DEPRECATED_discopop_wizard/classes/Settings.py b/DEPRECATED_discopop_wizard/classes/Settings.py deleted file mode 100644 index a45e17192..000000000 --- a/DEPRECATED_discopop_wizard/classes/Settings.py +++ /dev/null @@ -1,155 +0,0 @@ -# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) -# -# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany -# -# This software may be modified and distributed under the terms of -# the 3-Clause BSD License. See the LICENSE file in the package base -# directory for details. - -import os -import shutil - -import jsons # type:ignore - - -class Settings(object): - # general settings - initialized = False - discopop_build_dir: str = "" - clang: str = "" - clangpp: str = "" - llvm_ar: str = "" - llvm_link: str = "" - llvm_dis: str = "" - llvm_opt: str = "" - llvm_llc: str = "" - go_bin: str = "" - use_docker_container_for_profiling: bool = True - - # code preview settings - code_preview_show_metadata_regions: int = 0 # 1 = True, 0 = False - code_preview_show_metadata_live_device_variables: int = 0 # 1 = True, 0 = False - code_preview_show_line_numbers: int = 1 # 1 = True, 0 = False - code_preview_disable_compile_check: int = 0 # 1 = True, 0 = False - - def __init__(self, discopop_build_dir="", go_bin_dir="", use_docker_container: bool = True) -> None: - self.discopop_build_dir = discopop_build_dir - self.go_bin = go_bin_dir - self.use_docker_container_for_profiling = use_docker_container - # validate settings - settings_valid = os.path.exists(self.discopop_build_dir) and os.path.exists(self.go_bin) - - # get llvm_bin_dir from stored build configuration - llvm_bin_dir = "" - if settings_valid: - command = "cat " + self.discopop_build_dir + '/build_config.txt | grep -oP "(?<=LLVM_BIN_DIR=).*"' - llvm_bin_dir = os.popen(command).read().replace("\n", "") - if not os.path.exists(llvm_bin_dir): - llvm_bin_dir = "" - - # try and find default values using llvm_bin_dir and shutil.which - if os.path.exists(os.path.join(llvm_bin_dir, "clang")): - self.clang = os.path.join(llvm_bin_dir, "clang") - else: - self.clang = shutil.which("clang") or "" - if os.path.exists(os.path.join(llvm_bin_dir, "clang++")): - self.clangpp = os.path.join(llvm_bin_dir, "clang++") - else: - self.clangpp = shutil.which("clang++") or "" - - if os.path.exists(os.path.join(llvm_bin_dir, "llvm-ar")): - self.llvm_ar = os.path.join(llvm_bin_dir, "llvm-ar") - else: - self.llvm_ar = shutil.which("llvm-ar-11") or "" - - if os.path.exists(os.path.join(llvm_bin_dir, "llvm-link")): - self.llvm_link = os.path.join(llvm_bin_dir, "llvm-link") - else: - self.llvm_link = shutil.which("llvm-link-11") or "" - - if os.path.exists(os.path.join(llvm_bin_dir, "llvm-dis")): - self.llvm_dis = os.path.join(llvm_bin_dir, "llvm-dis") - else: - self.llvm_dis = shutil.which("llvm-dis-11") or "" - - if os.path.exists(os.path.join(llvm_bin_dir, "opt")): - self.llvm_opt = os.path.join(llvm_bin_dir, "opt") - else: - self.llvm_opt = shutil.which("opt-11") or "" - - if os.path.exists(os.path.join(llvm_bin_dir, "llc")): - self.llvm_llc = os.path.join(llvm_bin_dir, "llc") - else: - self.llvm_llc = shutil.which("llc-11") or "" - - # validate settings - settings_valid = ( - settings_valid - and len(self.clang) > 0 - and len(self.clangpp) > 0 - and len(self.llvm_ar) > 0 - and len(self.llvm_link) > 0 - and len(self.llvm_dis) > 0 - and len(self.llvm_opt) > 0 - and len(self.llvm_llc) > 0 - ) - - # set initialized, if all values could be determined and are valid, or docker container is used - self.initialized = use_docker_container or settings_valid - - def get_as_json_string(self): - """returns a representation of the settings which will be stored in a configuration file.""" - return jsons.dumps(self) - - def save_to_file(self, config_dir: str): - settings_path = os.path.join(config_dir, "SETTINGS.txt") - # remove old config if present - if os.path.exists(settings_path): - os.remove(settings_path) - # write config to file - with open(settings_path, "w+") as f: - f.write(self.get_as_json_string()) - - -def load_from_config_file(config_dir: str) -> Settings: - json_str = "" - with open(os.path.join(config_dir, "SETTINGS.txt"), "r") as f: - for line in f.readlines(): - json_str += line - value_dict = jsons.loads(json_str) - settings = Settings() - - # general settings - settings.discopop_build_dir = __load_or_get_default(value_dict, "discopop_build_dir") - settings.clang = __load_or_get_default(value_dict, "clang") - settings.clangpp = __load_or_get_default(value_dict, "clangpp") - settings.llvm_ar = __load_or_get_default(value_dict, "llvm_ar") - settings.llvm_link = __load_or_get_default(value_dict, "llvm_link") - settings.llvm_dis = __load_or_get_default(value_dict, "llvm_dis") - settings.llvm_opt = __load_or_get_default(value_dict, "llvm_opt") - settings.llvm_llc = __load_or_get_default(value_dict, "llvm_llc") - settings.go_bin = __load_or_get_default(value_dict, "go_bin") - settings.use_docker_container_for_profiling = __load_or_get_default( - value_dict, "use_docker_container_for_profiling" - ) - # code preview settings - settings.code_preview_show_metadata_regions = __load_or_get_default( - value_dict, "code_preview_show_metadata_regions" - ) - settings.code_preview_show_line_numbers = __load_or_get_default(value_dict, "code_preview_show_line_numbers") - settings.code_preview_show_metadata_live_device_variables = __load_or_get_default( - value_dict, "code_preview_show_metadata_live_device_variables" - ) - settings.code_preview_disable_compile_check = __load_or_get_default( - value_dict, "code_preview_disable_compile_check" - ) - - settings.initialized = True - return settings - - -def __load_or_get_default(value_dict, key_name): - if key_name in value_dict: - return value_dict[key_name] - # get default value - return getattr(Settings(), key_name) diff --git a/DEPRECATED_discopop_wizard/classes/Suggestion.py b/DEPRECATED_discopop_wizard/classes/Suggestion.py deleted file mode 100644 index 06920694e..000000000 --- a/DEPRECATED_discopop_wizard/classes/Suggestion.py +++ /dev/null @@ -1,216 +0,0 @@ -# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) -# -# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany -# -# This software may be modified and distributed under the terms of -# the 3-Clause BSD License. See the LICENSE file in the package base -# directory for details. - -import os -import tkinter as tk -from enum import IntEnum -from pathlib import Path -from tkinter import ttk -from typing import Any, Dict, List, Tuple - -from discopop_library.CodeGenerator.classes.UnpackedSuggestion import UnpackedSuggestion -from DEPRECATED_discopop_wizard.classes.CodePreview import CodePreviewContentBuffer - - -class PragmaType(IntEnum): - PRAGMA = 1 - REGION = 2 - - -class Suggestion(UnpackedSuggestion): - def __init__(self, wizard, type_str: str, values: Dict[str, Any]): - super().__init__(type_str, values) - self.wizard = wizard - - def show_code_section(self, parent_frame: tk.Frame, execution_configuration): - # close elements of parent_frame - for c in parent_frame.winfo_children(): - c.destroy() - - # configure parent_frame - parent_frame.rowconfigure(0, weight=1) - parent_frame.columnconfigure(0, weight=1) - - # create content frame and scroll bars - source_code = tk.Text(parent_frame, wrap=tk.NONE) - source_code.grid(row=0, column=0, sticky="nsew") - - # create a Scrollbar and associate it with the content frame - y_scrollbar = ttk.Scrollbar(parent_frame, command=source_code.yview) - y_scrollbar.grid(row=0, column=1, sticky="nsew") - source_code["yscrollcommand"] = y_scrollbar.set - - x_scrollbar = ttk.Scrollbar(parent_frame, orient="horizontal", command=source_code.xview) - x_scrollbar.grid(row=1, column=0, columnspan=2, sticky="nsew") - source_code["xscrollcommand"] = x_scrollbar.set - - # load file mapping from project path - file_mapping: Dict[int, Path] = dict() - with open( - os.path.join(execution_configuration.value_dict["working_copy_path"], "FileMapping.txt"), - "r", - ) as f: - for line in f.readlines(): - line = line.replace("\n", "") - split_line = line.split("\t") - id = int(split_line[0]) - path = split_line[1] - file_mapping[id] = Path(path) - - # create CodePreview object - code_preview = CodePreviewContentBuffer(self.wizard, self.file_id, file_mapping[self.file_id]) - - # get and insert pragmas - pragmas = self.get_pragmas() - for pragma in pragmas: - compile_check_command = ( - "cd " - + execution_configuration.value_dict["working_copy_path"] - + " && make " - + execution_configuration.value_dict["make_flags"] - + " " - + execution_configuration.value_dict["make_target"] - ) - successful = code_preview.add_pragma( - file_mapping, - pragma, - [], - skip_compilation_check=True if self.wizard.settings.code_preview_disable_compile_check == 1 else False, - compile_check_command=compile_check_command, - ) - # if the addition resulted in a non-compilable file, add the pragma as a comment - if not successful: - # print error codes - self.wizard.console.print(code_preview.compile_result_buffer) - code_preview.add_pragma( - file_mapping, - pragma, - [], - add_as_comment=True, - skip_compilation_check=True, - compile_check_command=compile_check_command, - ) - - # show CodePreview - code_preview.show_in(source_code) - - # show targeted code section - code_preview.jump_to_first_modification(source_code) - - # disable source code text widget to disallow editing - source_code.config(state=tk.DISABLED) - - def get_as_button(self, frame: tk.Frame, code_preview_frame: tk.Frame, execution_configuration) -> tk.Button: - return tk.Button( - frame, - text=self.type + " @ " + self.values["start_line"], - command=lambda: self.show_code_section(code_preview_frame, execution_configuration), - ) - - def __insert_pragmas(self, source_code: tk.Text, pragmas: List[Tuple[int, int, str]]): - highlight_start_positions = [] - - idx = 0 - for start_line, end_line, pragma_str in sorted( - pragmas, reverse=True, key=lambda v: int(v[0]) - ): # sort reverse by line num - # add pragma string - source_code.insert(str(start_line) + ".0", " " + pragma_str + "\n") - # highlight inserted pragmas and their target code sections - pos = self.__highlight_code( - source_code, start_line, end_line + 1, idx - ) # +1 to account for added pragma line - highlight_start_positions.append(pos) - idx += 1 - - return sorted(highlight_start_positions, key=lambda value: int(value.split(".")[0])) - - def __highlight_code(self, source_code: tk.Text, start_line: int, end_line: int, index): - """highlights the specified lines in the source code preview and returns the used start position. - index is used to determine the color.""" - end_line_length = 200 - background_color = "#e5f2b3" if index % 2 == 0 else "#a4ed9a" - # highlight code - start_pos = str(start_line) + ".0" - end_pos = str(end_line) + "." + str(end_line_length) - source_code.tag_add("start" + str(index), start_pos, end_pos) - source_code.tag_config("start" + str(index), background=background_color, foreground="black") - return start_pos - - def __get_pragmas(self) -> List[Tuple[int, int, str]]: - """returns a list of source code lines and pragmas to be inserted into the code preview""" - pragmas = [] - if self.type == "do_all" or self.type == "reduction": - pragma = "#pragma omp parallel for " - if len(self.values["first_private"]) > 0: - pragma += "firstprivate(" + ",".join(self.values["first_private"]) + ") " - if len(self.values["private"]) > 0: - pragma += "private(" + ",".join(self.values["private"]) + ") " - if len(self.values["last_private"]) > 0: - pragma += "lastprivate(" + ",".join(self.values["last_private"]) + ") " - if len(self.values["shared"]) > 0: - pragma += "shared(" + ",".join(self.values["shared"]) + ") " - if len(self.values["reduction"]) > 0: - reductions_dict: Dict[Any, Any] = dict() - for entry in self.values["reduction"]: - red_type = entry.split(":")[0] - var = entry.split(":")[1] - if red_type not in reductions_dict: - reductions_dict[red_type] = [] - reductions_dict[red_type].append(var) - for red_type in reductions_dict: - pragma += "reduction(" + red_type + ":" + ",".join(reductions_dict[red_type]) + ") " - pragma_tuple = (self.start_line, self.end_line, pragma) - pragmas.append(pragma_tuple) - return pragmas - elif self.type == "pipeline": - for stage in self.values["stages"]: - pragma = "#pragma omp task " - if len(stage["first_private"]) > 0: - pragma += "firstprivate(" + ",".join(stage["first_private"]) + ") " - if len(stage["private"]) > 0: - pragma += "private(" + ",".join(stage["private"]) + ") " - if len(stage["shared"]) > 0: - pragma += "shared(" + ",".join(stage["shared"]) + ") " - if len(stage["reduction"]) > 0: - reductions_dict = dict() - for entry in stage["reduction"]: - red_type = entry.split(":")[0] - var = entry.split(":")[1] - if red_type not in reductions_dict: - reductions_dict[red_type] = [] - reductions_dict[red_type].append(var) - for red_type in reductions_dict: - pragma += "reduction(" + red_type + ":" + ",".join(reductions_dict[red_type]) + ") " - if len(stage["in_deps"]) > 0: - pragma += "depends(in:" + ",".join(stage["in_deps"]) + ") " - if len(stage["out_deps"]) > 0: - pragma += "depends(out:" + ",".join(stage["out_deps"]) + ") " - if len(stage["in_out_deps"]) > 0: - pragma += "depends(inout:" + ",".join(stage["in_out_deps"]) + ") " - pragma_tuple = ( - int(stage["startsAtLine"].split(":")[1]), - int(stage["endsAtLine"].split(":")[1]), - pragma, - ) - pragmas.append(pragma_tuple) - else: - pragmas.append( - ( - self.start_line, - self.end_line, - "#CURRENTLY UNSUPPORTED PREVIEW FOR TYPE: " + self.type, - ) - ) - return pragmas - - def get_details(self) -> str: - """Returns the details string which should be shown when hovering over the Suggestion button.""" - import pprint - - return pprint.pformat(self.values) diff --git a/DEPRECATED_discopop_wizard/classes/TKVarStorage.py b/DEPRECATED_discopop_wizard/classes/TKVarStorage.py deleted file mode 100644 index e046d2dda..000000000 --- a/DEPRECATED_discopop_wizard/classes/TKVarStorage.py +++ /dev/null @@ -1,47 +0,0 @@ -# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) -# -# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany -# -# This software may be modified and distributed under the terms of -# the 3-Clause BSD License. See the LICENSE file in the package base -# directory for details. - -import tkinter as tk - - -class TKVarStorage(object): - # code preview settings - toggle_var_code_preview_show_metadata_regions: tk.IntVar - toggle_var_code_preview_show_metadata_live_device_variables: tk.IntVar - toggle_var_code_preview_show_line_numbers: tk.IntVar - toggle_var_code_preview_disable_compile_check: tk.IntVar - - def __init__(self, wizard): - self.wizard = wizard - self.toggle_var_code_preview_show_metadata_regions = tk.IntVar( - value=self.wizard.settings.code_preview_show_metadata_regions - ) - self.toggle_var_code_preview_show_line_numbers = tk.IntVar( - value=self.wizard.settings.code_preview_show_line_numbers - ) - self.toggle_var_code_preview_show_metadata_live_device_variables = tk.IntVar( - value=self.wizard.settings.code_preview_show_metadata_live_device_variables - ) - self.toggle_var_code_preview_disable_compile_check = tk.IntVar( - value=self.wizard.settings.code_preview_disable_compile_check - ) - - def toggle_code_preview_setting_action(self): - """overwrites the respective value in wizard.settings and triggers saving the new settings.""" - self.wizard.settings.code_preview_show_metadata_regions = ( - self.toggle_var_code_preview_show_metadata_regions.get() - ) - self.wizard.settings.code_preview_show_metadata_live_device_variables = ( - self.toggle_var_code_preview_show_metadata_live_device_variables.get() - ) - self.wizard.settings.code_preview_show_line_numbers = self.toggle_var_code_preview_show_line_numbers.get() - self.wizard.settings.code_preview_disable_compile_check = ( - self.toggle_var_code_preview_disable_compile_check.get() - ) - self.wizard.settings.save_to_file(self.wizard.config_dir) - self.wizard.console.print("Saved settings.") diff --git a/DEPRECATED_discopop_wizard/classes/__init__.py b/DEPRECATED_discopop_wizard/classes/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/DEPRECATED_discopop_wizard/headless/__init__.py b/DEPRECATED_discopop_wizard/headless/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/DEPRECATED_discopop_wizard/headless/headless_execution.py b/DEPRECATED_discopop_wizard/headless/headless_execution.py deleted file mode 100644 index 83ea937b2..000000000 --- a/DEPRECATED_discopop_wizard/headless/headless_execution.py +++ /dev/null @@ -1,65 +0,0 @@ -# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) -# -# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany -# -# This software may be modified and distributed under the terms of -# the 3-Clause BSD License. See the LICENSE file in the package base -# directory for details. - -import os -from typing import List, Tuple - -from DEPRECATED_discopop_wizard.classes.Arguments import Arguments -from DEPRECATED_discopop_wizard.classes.ExecutionConfiguration import ExecutionConfiguration -from DEPRECATED_discopop_wizard.classes.Settings import load_from_config_file, Settings -from DEPRECATED_discopop_wizard.screens.execution import ExecutionView -from DEPRECATED_discopop_wizard.wizard import DiscoPoPConfigurationWizard - - -def execute_all_stored_configurations(args: Arguments, source_dir: str): - wizard, settings, execution_configs = __load_data(args, source_dir) - # execute all configurations - execution_views: List[ExecutionView] = [] - for config in execution_configs: - execution_views.append(ExecutionView(config, wizard, None, headless_mode=True)) - - -def execute_tag_filtered_configurations(args: Arguments, source_dir: str): - wizard, settings, execution_configs = __load_data(args, source_dir) - # filter configurations by tags - filtered_execution_configs: List[ExecutionConfiguration] = [] - for config in execution_configs: - # get tags from config - # get tags from arguments - # if an overlap exists, the configurations shall be executed - overlapping_tags = [tag for tag in config.get_tags() if tag in args.execute_configurations_with_tag] - if len(overlapping_tags) > 0: - filtered_execution_configs.append(config) - - # execute the filtered configurations - execution_views: List[ExecutionView] = [] - for config in filtered_execution_configs: - execution_views.append(ExecutionView(config, wizard, None, headless_mode=True)) - - -def __load_data( - args: Arguments, source_dir: str -) -> Tuple[DiscoPoPConfigurationWizard, Settings, List[ExecutionConfiguration]]: - """Loads and returns a DiscoPoPConfigurationWizard, Settings, and a list of ExecutionConfigurations.""" - config_dir = os.path.join(source_dir, ".config") - # load settings - settings = load_from_config_file(config_dir) - # create DiscoPoPWizard - wizard = DiscoPoPConfigurationWizard(config_dir, args, headless_mode=True) - - # load execution configurations - execution_configs: List[ExecutionConfiguration] = [] - for filename in os.listdir(os.path.join(config_dir, "execution_configurations")): - if not filename.endswith(".json"): - continue - with open(os.path.join(os.path.join(config_dir, "execution_configurations"), filename), "r") as json_file: - config = ExecutionConfiguration(wizard) - config.init_from_json(json_file) - execution_configs.append(config) - - return wizard, settings, execution_configs diff --git a/DEPRECATED_discopop_wizard/screens/__init__.py b/DEPRECATED_discopop_wizard/screens/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/DEPRECATED_discopop_wizard/screens/execution.py b/DEPRECATED_discopop_wizard/screens/execution.py deleted file mode 100644 index 011c84f87..000000000 --- a/DEPRECATED_discopop_wizard/screens/execution.py +++ /dev/null @@ -1,105 +0,0 @@ -# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) -# -# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany -# -# This software may be modified and distributed under the terms of -# the 3-Clause BSD License. See the LICENSE file in the package base -# directory for details. - -import subprocess -import tkinter as tk -from typing import Optional, cast - -from DEPRECATED_discopop_wizard.classes.ProfilingContainer import ProfilingContainer -from DEPRECATED_discopop_wizard.screens.suggestions.overview import show_suggestions_overview_screen - - -class ExecutionView(object): - def __init__( - self, - execution_configuration, - wizard, - details_frame: Optional[tk.Frame], - headless_mode: bool = False, - ): - self.execution_configuration = execution_configuration - self.wizard = wizard - self.details_frame = details_frame - self.headless_mode = headless_mode - self.__execute() - - def __execute(self): - # prepare environment - if self.wizard.settings.use_docker_container_for_profiling: - # start container if not already present. Required when enabling container usage after start of application. - if self.wizard.profiling_container is None: - self.wizard.profiling_container = ProfilingContainer(self.wizard) - self.wizard.profiling_container.analyze_project(self) - # todo add display of suggestions - if not self.headless_mode: - self.__show_suggestions() - else: - # prepare command - command = self.__assemble_command_string() - # execute command - return_code = self.__execute_command(command) - if return_code == 0: - # show suggestions, stored in project_path/patterns.txt - if not self.headless_mode: - self.__show_suggestions() - - def __assemble_command_string(self) -> str: - # assemble command for regular execution - command = "" - # settings - command = self.wizard.settings.discopop_build_dir + "/scripts/runDiscoPoP " - command += '--llvm-clang "' + self.wizard.settings.clang + '" ' - command += '--llvm-clang++ "' + self.wizard.settings.clangpp + '" ' - command += '--llvm-ar "' + self.wizard.settings.llvm_ar + '" ' - command += '--llvm-link "' + self.wizard.settings.llvm_link + '" ' - command += '--llvm-dis "' + self.wizard.settings.llvm_dis + '" ' - command += '--llvm-opt "' + self.wizard.settings.llvm_opt + '" ' - command += '--llvm-llc "' + self.wizard.settings.llvm_llc + '" ' - command += '--gllvm "' + self.wizard.settings.go_bin + '" ' - # execution configuration - command += '--project "' + self.execution_configuration.value_dict["project_path"] + '" ' - command += '--linker-flags "' + self.execution_configuration.value_dict["linker_flags"] + '" ' - command += '--executable-name "' + self.execution_configuration.value_dict["executable_name"] + '" ' - command += '--executable-arguments "' + self.execution_configuration.value_dict["executable_arguments"] + '" ' - command += '--make-flags "' + self.execution_configuration.value_dict["make_flags"] + '" ' - command += '--make-target "' + self.execution_configuration.value_dict["make_target"] + '" ' - command += ( - "--memory-profiling-skip-function-arguments " - if self.execution_configuration.value_dict["memory_profiling_skip_function_parameters"] == 1 - else "" - ) - command += '--explorer-flags "' + self.execution_configuration.value_dict["explorer_flags"] + '" ' - - return command - - def __execute_command(self, command: str) -> int: - with subprocess.Popen(command, stdout=subprocess.PIPE, bufsize=1, universal_newlines=True, shell=True) as p: - if p.stdout is None: - print("command execution was not successfull") - else: - for line in p.stdout: - line = line.replace("\n", "") - self.__print_to_console(line) - if not self.headless_mode: - self.wizard.console.print(line) - if p.returncode != 0: - self.__print_to_console("An error occurred during the execution!") # Error message - if not self.headless_mode: - self.wizard.console.print("An error occurred during the execution!") - for line in str(subprocess.CalledProcessError(p.returncode, p.args)).split("\n"): - line = line.replace("\n", "") - self.__print_to_console(line) - if not self.headless_mode: - self.wizard.console.print(line) - return p.returncode - - def __print_to_console(self, msg: str): - print(msg) - - def __show_suggestions(self): - show_suggestions_overview_screen(self.wizard, cast(tk.Frame, self.details_frame), self.execution_configuration) diff --git a/DEPRECATED_discopop_wizard/screens/main.py b/DEPRECATED_discopop_wizard/screens/main.py deleted file mode 100644 index 671169ceb..000000000 --- a/DEPRECATED_discopop_wizard/screens/main.py +++ /dev/null @@ -1,143 +0,0 @@ -# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) -# -# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany -# -# This software may be modified and distributed under the terms of -# the 3-Clause BSD License. See the LICENSE file in the package base -# directory for details. -import os.path -import tkinter as tk -from tkinter import ttk -from typing import List - -from DEPRECATED_discopop_wizard.classes.ExecutionConfiguration import ExecutionConfiguration -from DEPRECATED_discopop_wizard.screens.settings import show_settings_screen -from DEPRECATED_discopop_wizard.utils import support_scrolling - - -class MainScreen(object): - configuration_frame: tk.Frame - notebook: ttk.Notebook - details_frame: tk.Frame - results_frame: tk.Frame - - toggle_var_code_preview_show_metadata: tk.IntVar - - def __init__(self, wizard, window_frame: tk.Frame): - self.wizard = wizard - self.push_main_screen(wizard, window_frame) - - def push_main_screen(self, wizard, window_frame: tk.Frame): - frame = tk.Frame(window_frame) - frame.grid(row=1, column=1, sticky="nsew") - - # create horizontally split frames (configurations + details frame) - horizontal_paned_window = ttk.PanedWindow(frame, orient="horizontal") - horizontal_paned_window.pack(fill=tk.BOTH, expand=True) - self.configuration_frame = tk.Frame(horizontal_paned_window) - horizontal_paned_window.add(self.configuration_frame) - self.notebook = ttk.Notebook(horizontal_paned_window) - horizontal_paned_window.add(self.notebook, weight=1) - - self.details_frame = tk.Frame(self.notebook) - self.results_frame = tk.Frame(self.notebook) - self.optimizer_frame = tk.Frame(self.notebook) - self.notebook.add(self.details_frame, text="Details") - self.notebook.add(self.results_frame, text="Results") - self.notebook.add(self.optimizer_frame, text="Optimizer (experimental)") - - self.build_configurations_frame(wizard) - - self.__build_menu_bar(wizard) - - def __build_menu_bar(self, wizard): - # build menu bar - optionsmenu = tk.Menu(wizard.menubar) - wizard.menubar.add_cascade(label="Options", menu=optionsmenu) - optionsmenu.add_command(label="Settings", command=lambda: show_settings_screen(wizard)) - # build code preview menu - code_preview_menu = tk.Menu(optionsmenu) - optionsmenu.add_cascade(label="Code Preview", menu=code_preview_menu) - code_preview_menu.add_checkbutton( - label="Show Metadata Regions", - variable=wizard.tk_var_storage.toggle_var_code_preview_show_metadata_regions, - onvalue=1, - offvalue=0, - command=lambda: wizard.tk_var_storage.toggle_code_preview_setting_action(), - ) - code_preview_menu.add_checkbutton( - label="Show Line Numbers", - variable=wizard.tk_var_storage.toggle_var_code_preview_show_line_numbers, - onvalue=1, - offvalue=0, - command=lambda: wizard.tk_var_storage.toggle_code_preview_setting_action(), - ) - code_preview_menu.add_checkbutton( - label="Show Live Variables", - variable=wizard.tk_var_storage.toggle_var_code_preview_show_metadata_live_device_variables, - onvalue=1, - offvalue=0, - command=lambda: wizard.tk_var_storage.toggle_code_preview_setting_action(), - ) - code_preview_menu.add_checkbutton( - label="Disable compile validation of inserted pragmas", - variable=wizard.tk_var_storage.toggle_var_code_preview_disable_compile_check, - onvalue=1, - offvalue=0, - command=lambda: wizard.tk_var_storage.toggle_code_preview_setting_action(), - ) - - def build_configurations_frame(self, wizard): - # clear previous contents if existent - for c in self.configuration_frame.winfo_children(): - c.destroy() - # build configuration frame - self.__display_execution_configurations(wizard) - - def __create_new_execution_configuration(self, wizard): - execution_config = ExecutionConfiguration(wizard) - execution_config.show_details_screen(wizard, self) - - def __display_execution_configurations(self, wizard): - # based on https://blog.teclado.com/tkinter-scrollable-frames/ - # load configuration options - configs: List[ExecutionConfiguration] = self.load_execution_configurations(wizard.config_dir) - frame = tk.Frame(self.configuration_frame) - frame.pack(fill=tk.BOTH, expand=True) - tk.Label(frame, text="Configurations", font=wizard.style_font_bold, pady=10).pack() - # add New.. Button - tk.Button(frame, text="New..", command=lambda: self.__create_new_execution_configuration(wizard)).pack() - - tmp_frame = tk.Frame(frame) - tmp_frame.pack(fill=tk.BOTH, expand=True) - - # create scrollable list of suggestions - canvas = tk.Canvas(tmp_frame) - scrollbar = tk.Scrollbar(tmp_frame, orient="vertical", command=canvas.yview) - scrollable_frame = tk.Frame(canvas) - scrollable_frame.bind("", lambda e: canvas.configure(scrollregion=canvas.bbox("all"))) - canvas.create_window((0, 0), window=scrollable_frame, anchor="nw") - canvas.configure(yscrollcommand=scrollbar.set) - - all_buttons: List[tk.Button] = [] # used to manage highlights when a different configuration is selected - for row, config in enumerate(configs): - button = config.get_as_button(wizard, self, scrollable_frame, all_buttons) - button.pack(fill=tk.BOTH, expand=True) - all_buttons.append(button) - - # support scrolling on all platforms (linux, windows, macOS) - support_scrolling(canvas) - - canvas.pack(side="left", fill="both", expand=True) - scrollbar.pack(side="right", fill="y") - - def load_execution_configurations(self, config_dir: str) -> List[ExecutionConfiguration]: - execution_configs: List[ExecutionConfiguration] = [] - for filename in os.listdir(os.path.join(config_dir, "execution_configurations")): - if not filename.endswith(".json"): - continue - with open(os.path.join(os.path.join(config_dir, "execution_configurations"), filename), "r") as json_file: - config = ExecutionConfiguration(self.wizard) - config.init_from_json(json_file) - execution_configs.append(config) - return execution_configs diff --git a/DEPRECATED_discopop_wizard/screens/optimizer/__init__.py b/DEPRECATED_discopop_wizard/screens/optimizer/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/DEPRECATED_discopop_wizard/screens/optimizer/binding.py b/DEPRECATED_discopop_wizard/screens/optimizer/binding.py deleted file mode 100644 index f44a13326..000000000 --- a/DEPRECATED_discopop_wizard/screens/optimizer/binding.py +++ /dev/null @@ -1,145 +0,0 @@ -# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) -# -# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany -# -# This software may be modified and distributed under the terms of -# the 3-Clause BSD License. See the LICENSE file in the package base -# directory for details. -import tkinter as tk -from tkinter import filedialog -import warnings - -from discopop_library.PathManagement.PathManagement import get_path - - -def create_optimizer_screen(wizard, parent_frame, execution_configuration): - # close elements on optimizer_frame - for c in parent_frame.winfo_children(): - c.destroy() - - canvas = tk.Canvas(parent_frame) - canvas.pack(fill=tk.BOTH) - - arguments = dict() - - def overwrite_with_file_selection(target: tk.Entry): - prompt_result = filedialog.askopenfilename() - if len(prompt_result) != 0: - target.delete(0, tk.END) - target.insert(0, prompt_result) - - ### - tk.Label( - canvas, - text="Compile_command", - justify=tk.RIGHT, - anchor="e", - font=wizard.style_font_bold_small, - ).grid(row=1, column=0, sticky="ew") - compile_command = tk.Entry(canvas, width=100) - compile_command.insert(tk.END, "make") - compile_command.grid(row=1, column=1, sticky="ew") - ### - tk.Label( - canvas, - text="DoAll microbench file", - justify=tk.RIGHT, - anchor="e", - font=wizard.style_font_bold_small, - ).grid(row=2, column=0, sticky="ew") - doall_microbench_file = tk.Entry(canvas, width=100) - doall_microbench_file.insert(tk.END, "None") - doall_microbench_file.grid(row=2, column=1, sticky="ew") - - doall_microbench_file_path_selector = tk.Button( - canvas, text="Select", command=lambda: overwrite_with_file_selection(doall_microbench_file) - ) - doall_microbench_file_path_selector.grid(row=2, column=3) - ### - tk.Label( - canvas, - text="Reduction microbench file", - justify=tk.RIGHT, - anchor="e", - font=wizard.style_font_bold_small, - ).grid(row=3, column=0, sticky="ew") - reduction_microbench_file = tk.Entry(canvas, width=100) - reduction_microbench_file.insert(tk.END, "None") - reduction_microbench_file.grid(row=3, column=1, sticky="ew") - - reduction_microbench_file_path_selector = tk.Button( - canvas, - text="Select", - command=lambda: overwrite_with_file_selection(reduction_microbench_file), - ) - reduction_microbench_file_path_selector.grid(row=3, column=3) - ### - tk.Label( - canvas, - text="Exhaustive search", - justify=tk.RIGHT, - anchor="e", - font=wizard.style_font_bold_small, - ).grid(row=4, column=0, sticky="ew") - exhaustive_search = tk.IntVar(canvas) - exhaustive_search.set(0) - cb = tk.Checkbutton(canvas, onvalue=1, offvalue=0, variable=exhaustive_search) - cb.grid(row=4, column=1) - - start_button = tk.Button( - canvas, - text="Start Optimizer for " + execution_configuration.value_dict["label"], - command=lambda: __start_optimizer( - execution_configuration, - compile_command, - doall_microbench_file, - reduction_microbench_file, - exhaustive_search, - parent_frame, - ), - ) - start_button.grid(row=5, column=0) - - -def __start_optimizer( - execution_configuration, - compile_command, - doall_microbench_file, - reduction_microbench_file, - exhaustive_search, - parent_frame, -): - arguments = { - "--project": execution_configuration.value_dict["project_path"], - "--detection-result-dump": get_path( - execution_configuration.value_dict["working_copy_path"], "detection_result_dump.json" - ), - "--execute-created-models": False, - "--clean-created-code": False, - "--code-export-path": get_path( - execution_configuration.value_dict["project_path"], ".discopop_optimizer/code_exports" - ), - "--dp-output-path": execution_configuration.value_dict["working_copy_path"], - "--file-mapping": get_path(execution_configuration.value_dict["working_copy_path"], "FileMapping.txt"), - "--executable-arguments": execution_configuration.value_dict["executable_arguments"], - "--executable-name": execution_configuration.value_dict["executable_name"], - "--linker-flags": execution_configuration.value_dict["linker_flags"], - "--make-target": execution_configuration.value_dict["make_target"], - "--make-flags": execution_configuration.value_dict["make_flags"], - "--execution-repetitions": 1, - "--execute-single-model": False, - "--compile-command": compile_command.get(), - "--execution-append-measurements": False, - "--exhaustive-search": True if exhaustive_search.get() == 1 else False, - "--headless-mode": False, - "--doall-microbench-file": doall_microbench_file.get(), - "--reduction-microbench-file": reduction_microbench_file.get(), - "--dp-optimizer-path": get_path(execution_configuration.value_dict["project_path"], ".discopop_optimizer"), - } - - # close elements on optimizer_frame - for c in parent_frame.winfo_children(): - c.destroy() - - # start_optimizer(arguments, parent_frame=parent_frame) - warnings.warn("TODO: BINDING TO OPTIMIZER CURRENTLY NOT IMPLEMENTED!") diff --git a/DEPRECATED_discopop_wizard/screens/settings.py b/DEPRECATED_discopop_wizard/screens/settings.py deleted file mode 100644 index bd209bf59..000000000 --- a/DEPRECATED_discopop_wizard/screens/settings.py +++ /dev/null @@ -1,180 +0,0 @@ -# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) -# -# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany -# -# This software may be modified and distributed under the terms of -# the 3-Clause BSD License. See the LICENSE file in the package base -# directory for details. - -import tkinter as tk -from tkinter import filedialog -from tkinter import ttk - -from DEPRECATED_discopop_wizard.screens.utils import create_tool_tip - - -def show_settings_screen(wizard): - # clear content frame - for c in wizard.window_frame.winfo_children(): - c.destroy() - - # build settings frame - frame = tk.Frame(wizard.window_frame) - frame.grid(row=1, column=1) - - # show labels - tk.Label(frame, text="Directories:", justify=tk.RIGHT, font=wizard.style_font_bold).grid( - row=1, column=1, sticky="ew" - ) - tk.Label(frame, text="DiscoPoP build:", justify=tk.RIGHT, anchor="e").grid(row=3, column=1, sticky="ew") - tk.Label(frame, text="go/bin directory:", justify=tk.RIGHT, anchor="e").grid(row=4, column=1, sticky="ew") - - ttk.Separator(frame, orient="horizontal").grid(row=5, column=1, sticky="ew", pady=10) - tk.Label(frame, text="Executables:", justify=tk.RIGHT, font=wizard.style_font_bold).grid(row=6, column=1) - tk.Label(frame, text="clang:", justify=tk.RIGHT, anchor="e").grid(row=7, column=1, sticky="ew") - tk.Label(frame, text="clang++:", justify=tk.RIGHT, anchor="e").grid(row=8, column=1, sticky="ew") - tk.Label(frame, text="llvm-ar:", justify=tk.RIGHT, anchor="e").grid(row=9, column=1, sticky="ew") - tk.Label(frame, text="llvm-link:", justify=tk.RIGHT, anchor="e").grid(row=10, column=1, sticky="ew") - tk.Label(frame, text="llvm-dis:", justify=tk.RIGHT, anchor="e").grid(row=11, column=1, sticky="ew") - tk.Label(frame, text="llvm-opt:", justify=tk.RIGHT, anchor="e").grid(row=12, column=1, sticky="ew") - tk.Label(frame, text="llvm-llc:", justify=tk.RIGHT, anchor="e").grid(row=13, column=1, sticky="ew") - - ttk.Separator(frame, orient="horizontal").grid(row=14, column=1, sticky="ew", pady=10) - tk.Label(frame, text="Options:", justify=tk.RIGHT, font=wizard.style_font_bold).grid(row=15, column=1) - tk.Label(frame, text="Use Docker Container for profiling:", justify=tk.RIGHT, anchor="e").grid( - row=16, column=1, sticky="ew" - ) - - def __get_field_state(): - return tk.DISABLED if wizard.settings.use_docker_container_for_profiling else tk.NORMAL - - # show input fields - discopop_build = tk.Entry(frame) - discopop_build.grid(row=3, column=2, sticky="ew") - discopop_build.insert(tk.END, wizard.settings.discopop_build_dir) - discopop_build.config(state=__get_field_state()) - create_tool_tip(discopop_build, "Path to DiscoPoP build directory.") - - go_bin_path = tk.Entry(frame) - go_bin_path.grid(row=4, column=2, sticky="ew") - go_bin_path.insert(tk.END, wizard.settings.go_bin) - go_bin_path.config(state=__get_field_state()) - create_tool_tip(go_bin_path, "Path to the bin folder inside the installation folder of Go.") - - clang = tk.Entry(frame, width=50) - clang.grid(row=7, column=2, sticky="ew") - clang.insert(tk.END, wizard.settings.clang) - clang.config(state=__get_field_state()) - create_tool_tip(clang, "Path to the clang executable.") - - clangpp = tk.Entry(frame) - clangpp.grid(row=8, column=2, sticky="ew") - clangpp.insert(tk.END, wizard.settings.clangpp) - clangpp.config(state=__get_field_state()) - create_tool_tip(clangpp, "Path to the clang++ executable.") - - llvm_ar = tk.Entry(frame) - llvm_ar.grid(row=9, column=2, sticky="ew") - llvm_ar.insert(tk.END, wizard.settings.llvm_ar) - llvm_ar.config(state=__get_field_state()) - create_tool_tip(llvm_ar, "Path to the llvm-ar executable.") - - llvm_link = tk.Entry(frame) - llvm_link.grid(row=10, column=2, sticky="ew") - llvm_link.insert(tk.END, wizard.settings.llvm_link) - llvm_link.config(state=__get_field_state()) - create_tool_tip(llvm_link, "Path to the llvm_link executable.") - - llvm_dis = tk.Entry(frame) - llvm_dis.grid(row=11, column=2, sticky="ew") - llvm_dis.insert(tk.END, wizard.settings.llvm_dis) - llvm_dis.config(state=__get_field_state()) - create_tool_tip(llvm_dis, "Path to the llvm_dis executable.") - - llvm_opt = tk.Entry(frame) - llvm_opt.grid(row=12, column=2, sticky="ew") - llvm_opt.insert(tk.END, wizard.settings.llvm_opt) - llvm_opt.config(state=__get_field_state()) - create_tool_tip(llvm_opt, "Path to the llvm_opt executable.") - - llvm_llc = tk.Entry(frame) - llvm_llc.grid(row=13, column=2, sticky="ew") - llvm_llc.insert(tk.END, wizard.settings.llvm_llc) - llvm_llc.config(state=__get_field_state()) - create_tool_tip(llvm_llc, "Path to the llvm_llc executable.") - - use_docker_container_var = tk.IntVar(value=1 if wizard.settings.use_docker_container_for_profiling else 0) - use_docker_container = tk.Checkbutton(frame, variable=use_docker_container_var) - create_tool_tip( - use_docker_container, - "When un-checking, please save and re-open" " the settings to enable input fields!", - ) - - use_docker_container.grid(row=16, column=2) - - # show path selector buttons - tk.Button(frame, text="Select", command=lambda: __overwrite_with_selection(discopop_build)).grid(row=3, column=3) - tk.Button(frame, text="Select", command=lambda: __overwrite_with_selection(go_bin_path)).grid(row=4, column=3) - tk.Button(frame, text="Select", command=lambda: __overwrite_with_selection(clang)).grid(row=7, column=3) - tk.Button(frame, text="Select", command=lambda: __overwrite_with_selection(clangpp)).grid(row=8, column=3) - tk.Button(frame, text="Select", command=lambda: __overwrite_with_selection(llvm_ar)).grid(row=9, column=3) - tk.Button(frame, text="Select", command=lambda: __overwrite_with_selection(llvm_link)).grid(row=10, column=3) - tk.Button(frame, text="Select", command=lambda: __overwrite_with_selection(llvm_dis)).grid(row=11, column=3) - tk.Button(frame, text="Select", command=lambda: __overwrite_with_selection(llvm_opt)).grid(row=12, column=3) - tk.Button(frame, text="Select", command=lambda: __overwrite_with_selection(llvm_llc)).grid(row=13, column=3) - - # show save button - tk.Button( - frame, - text="Save", - command=lambda: save_settings( - wizard, - discopop_build, - go_bin_path, - clang, - clangpp, - llvm_ar, - llvm_link, - llvm_dis, - llvm_opt, - llvm_llc, - use_docker_container_var, - ), - ).grid(row=17, column=2, pady=10) - - -def __overwrite_with_selection(target: tk.Entry): - prompt_result = tk.filedialog.askdirectory() - if len(prompt_result) != 0: - target.delete(0, tk.END) - target.insert(0, prompt_result) - - -def save_settings( - wizard, - discopop_build: tk.Entry, - go_bin_path: tk.Entry, - clang: tk.Entry, - clangpp: tk.Entry, - llvm_ar: tk.Entry, - llvm_link: tk.Entry, - llvm_dis: tk.Entry, - llvm_opt: tk.Entry, - llvm_llc: tk.Entry, - use_docker_container_var, -): - wizard.settings.discopop_build_dir = discopop_build.get() - wizard.settings.go_bin = go_bin_path.get() - wizard.settings.clang = clang.get() - wizard.settings.clangpp = clangpp.get() - wizard.settings.llvm_ar = llvm_ar.get() - wizard.settings.llvm_link = llvm_link.get() - wizard.settings.llvm_dis = llvm_dis.get() - wizard.settings.llvm_opt = llvm_opt.get() - wizard.settings.llvm_llc = llvm_llc.get() - wizard.settings.use_docker_container_for_profiling = True if use_docker_container_var.get() == 1 else False - - wizard.settings.save_to_file(config_dir=wizard.config_dir) - - # return to main screen - wizard.show_main_screen() diff --git a/DEPRECATED_discopop_wizard/screens/suggestions/__init__.py b/DEPRECATED_discopop_wizard/screens/suggestions/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/DEPRECATED_discopop_wizard/screens/suggestions/overview.py b/DEPRECATED_discopop_wizard/screens/suggestions/overview.py deleted file mode 100644 index 640352cc0..000000000 --- a/DEPRECATED_discopop_wizard/screens/suggestions/overview.py +++ /dev/null @@ -1,140 +0,0 @@ -# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) -# -# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany -# -# This software may be modified and distributed under the terms of -# the 3-Clause BSD License. See the LICENSE file in the package base -# directory for details. -import json -import os -import tkinter as tk -from tkinter import ttk -from typing import List - -from DEPRECATED_discopop_wizard.classes.Suggestion import Suggestion -from DEPRECATED_discopop_wizard.screens.utils import create_tool_tip -from DEPRECATED_discopop_wizard.screens.widgets.ScrollableText import ScrollableTextWidget -from DEPRECATED_discopop_wizard.utils import support_scrolling - - -def show_suggestions_overview_screen(wizard, details_frame: tk.Frame, execution_configuration_obj): - # close elements on details_frame - for c in details_frame.winfo_children(): - c.destroy() - # load suggestions from execution - suggestions = get_suggestion_objects(wizard, execution_configuration_obj) - - # create horizontally split frames (scrollable list of suggestions + code preview) - horizontal_paned_window = ttk.PanedWindow(details_frame, orient="horizontal") - horizontal_paned_window.pack(fill=tk.BOTH, expand=True) - scrollable_list_frame = tk.Frame(horizontal_paned_window) - horizontal_paned_window.add(scrollable_list_frame, weight=1) - code_preview_frame = tk.Frame(horizontal_paned_window) - horizontal_paned_window.add(code_preview_frame, weight=5) - - tmp_frame = tk.Frame(scrollable_list_frame) - tmp_frame.pack(fill=tk.BOTH, expand=True) - - # define notebook widget to show generated CUs and dependencies - separator = ttk.Separator(scrollable_list_frame, orient="horizontal") - separator.pack(fill=tk.X) - result_browser_frame = tk.Frame(scrollable_list_frame) - result_browser_frame.pack(fill=tk.BOTH, expand=True) - result_notebook = ttk.Notebook(result_browser_frame) - result_notebook.pack(fill=tk.BOTH, expand=True) - # add CU preview - cu_display_widget = ScrollableTextWidget(result_notebook) - with open(execution_configuration_obj.value_dict["working_copy_path"] + "/Data.xml", "r") as f: - cu_display_widget.set_text(f.read()) - result_notebook.add(cu_display_widget.frame, text="CU's") - # add dynamic dependency preview - dynamic_dep_display_widget = ScrollableTextWidget(result_notebook) - with open( - execution_configuration_obj.value_dict["working_copy_path"] - + "/" - + execution_configuration_obj.value_dict["executable_name"] - + "_dp_dep.txt", - "r", - ) as f: - dynamic_dep_display_widget.set_text(f.read()) - result_notebook.add(dynamic_dep_display_widget.frame, text="Dynamic DEP's") - # add static dependency preview - static_dep_display_widget = ScrollableTextWidget(result_notebook) - if os.path.exists(execution_configuration_obj.value_dict["working_copy_path"] + "/static_dependencies.txt"): - with open( - execution_configuration_obj.value_dict["working_copy_path"] + "/static_dependencies.txt", - "r", - ) as f: - static_dep_display_widget.set_text(f.read()) - else: - static_dep_display_widget.set_text( - execution_configuration_obj.value_dict["working_copy_path"] + "/static_dependencies.txt" + " NOT FOUND." - ) - result_notebook.add(static_dep_display_widget.frame, text="Static DEP's") - # add instrumented LLVM IR preview - instrumented_llvm_ir_display_widget = ScrollableTextWidget(result_notebook) - if os.path.exists( - execution_configuration_obj.value_dict["working_copy_path"] - + "/" - + execution_configuration_obj.value_dict["executable_name"] - + "_dp.ll" - ): - with open( - execution_configuration_obj.value_dict["working_copy_path"] - + "/" - + execution_configuration_obj.value_dict["executable_name"] - + "_dp.ll", - "r", - ) as f: - instrumented_llvm_ir_display_widget.set_text(f.read()) - else: - instrumented_llvm_ir_display_widget.set_text( - execution_configuration_obj.value_dict["working_copy_path"] - + "/" - + execution_configuration_obj.value_dict["executable_name"] - + "_dp.ll" - + " NOT FOUND." - ) - result_notebook.add(instrumented_llvm_ir_display_widget.frame, text="LLVM IR") - # add patterns.json preview - patterns_json_display_widget = ScrollableTextWidget(result_notebook) - with open(execution_configuration_obj.value_dict["working_copy_path"] + "/" + "patterns.json", "r") as f: - patterns_json_display_widget.set_text(f.read()) - result_notebook.add(patterns_json_display_widget.frame, text="patterns.json") - - # create scrollable list of suggestions - canvas = tk.Canvas(tmp_frame) - scrollbar = tk.Scrollbar(tmp_frame, orient="vertical", command=canvas.yview) - scrollable_frame = tk.Frame(canvas) - scrollable_frame.bind("", lambda e: canvas.configure(scrollregion=canvas.bbox("all"))) - canvas.create_window((0, 0), window=scrollable_frame, anchor="nw") - canvas.configure(yscrollcommand=scrollbar.set) - for row, suggestion in enumerate(suggestions): - # create button to load code preview - button = suggestion.get_as_button(scrollable_frame, code_preview_frame, execution_configuration_obj) - button.pack(fill=tk.BOTH, expand=True) - - # register hover message (suggestion details) - create_tool_tip(button, text=suggestion.get_details()) - - # add support for mouse wheel scrolling - support_scrolling(canvas) - - # add label - tk.Label(tmp_frame, text="Suggestions", font=wizard.style_font_bold).pack(side="top", pady=10) - - canvas.pack(side="left", fill="both", expand=True) - scrollbar.pack(side="right", fill="y") - - -def get_suggestion_objects(wizard, execution_configuration_obj) -> List[Suggestion]: - suggestions_path = os.path.join(execution_configuration_obj.value_dict["working_copy_path"], "patterns.json") - - suggestions_list: List[Suggestion] = [] - with open(suggestions_path, "r") as f: - suggestions_dict = json.load(f) - for suggestion_type in suggestions_dict: - for suggestion_values in suggestions_dict[suggestion_type]: - suggestions_list.append(Suggestion(wizard, suggestion_type, suggestion_values)) - - return suggestions_list diff --git a/DEPRECATED_discopop_wizard/screens/utils.py b/DEPRECATED_discopop_wizard/screens/utils.py deleted file mode 100644 index 55e655535..000000000 --- a/DEPRECATED_discopop_wizard/screens/utils.py +++ /dev/null @@ -1,60 +0,0 @@ -# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) -# -# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany -# -# This software may be modified and distributed under the terms of -# the 3-Clause BSD License. See the LICENSE file in the package base -# directory for details. -import tkinter as tk - - -class ToolTip(object): - # based on https://stackoverflow.com/questions/20399243/display-message-when-hovering-over-something-with-mouse-cursor-in-python - - def __init__(self, widget): - self.widget = widget - self.tip_window = None - self.id = None - self.x = self.y = 0 - self.text = "" - - def showtip(self, text): - """Display text in tooltip window""" - self.text = text - if self.tip_window or not self.text: - return - x, y, cx, cy = self.widget.bbox("insert") - x = x + self.widget.winfo_rootx() + 57 - y = y + cy + self.widget.winfo_rooty() + 27 - self.tip_window = tw = tk.Toplevel(self.widget) - tw.wm_overrideredirect(True) - tw.wm_geometry("+%d+%d" % (x, y)) - label = tk.Label( - tw, - text=self.text, - justify=tk.LEFT, - background="#ffffe0", - relief=tk.SOLID, - borderwidth=1, - font=("tahoma", 8, "normal"), - ) - label.pack(ipadx=1) - - def hidetip(self): - tw = self.tip_window - self.tip_window = None - if tw: - tw.destroy() - - -def create_tool_tip(widget, text): - tool_tip = ToolTip(widget) - - def enter(event): - tool_tip.showtip(text) - - def leave(event): - tool_tip.hidetip() - - widget.bind("", enter) - widget.bind("", leave) diff --git a/DEPRECATED_discopop_wizard/screens/widgets/__init__.py b/DEPRECATED_discopop_wizard/screens/widgets/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/DEPRECATED_discopop_wizard/utils.py b/DEPRECATED_discopop_wizard/utils.py deleted file mode 100644 index 3087a882d..000000000 --- a/DEPRECATED_discopop_wizard/utils.py +++ /dev/null @@ -1,65 +0,0 @@ -# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) -# -# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany -# -# This software may be modified and distributed under the terms of -# the 3-Clause BSD License. See the LICENSE file in the package base -# directory for details. - - -import functools -from enum import Enum -from sys import platform - - -class Platform(Enum): - UNKNOWN = 0 - LINUX = 1 - WINDOWS = 2 - OSX = 3 - - -def get_platform(): - platforms = { - "linux1": Platform.LINUX, - "linux2": Platform.LINUX, - "darwin": Platform.OSX, - "win32": Platform.WINDOWS, - } - if platform not in platforms: - return Platform.UNKNOWN - - return platforms[platform] - - -def support_scrolling(canvas): - # add support for mouse wheel scrolling (on linux systems) - def _on_mousewheel(event, scroll): - canvas.yview_scroll(int(scroll), "units") - - def _bind_to_mousewheel(event): - pf = get_platform() - if pf == Platform.LINUX: - canvas.bind_all("", functools.partial(_on_mousewheel, scroll=-1)) - canvas.bind_all("", functools.partial(_on_mousewheel, scroll=1)) - elif pf == Platform.WINDOWS: - canvas.bind_all("", functools.partial(_on_mousewheel, scroll=(-1 * (event.delta / 120)))) - elif pf == Platform.OSX: - canvas.bind_all("", functools.partial(_on_mousewheel, scroll=-1 * event.delta)) - else: - canvas.bind_all("", functools.partial(_on_mousewheel, scroll=-1)) - canvas.bind_all("", functools.partial(_on_mousewheel, scroll=1)) - - def _unbind_from_mousewheel(event): - pf = get_platform() - if pf == Platform.LINUX: - canvas.unbind_all("") - canvas.unbind_all("") - elif pf == Platform.WINDOWS or pf == Platform.OSX: - canvas.unbind_all("") - else: - canvas.unbind_all("") - canvas.unbind_all("") - - canvas.bind("", _bind_to_mousewheel) - canvas.bind("", _unbind_from_mousewheel) diff --git a/DEPRECATED_discopop_wizard/wizard.py b/DEPRECATED_discopop_wizard/wizard.py deleted file mode 100644 index 7dbfe9908..000000000 --- a/DEPRECATED_discopop_wizard/wizard.py +++ /dev/null @@ -1,187 +0,0 @@ -# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) -# -# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany -# -# This software may be modified and distributed under the terms of -# the 3-Clause BSD License. See the LICENSE file in the package base -# directory for details. - -import os -import pathlib -import signal -import tkinter as tk -import warnings -from enum import IntEnum -from os.path import dirname -from tkinter import messagebox, filedialog -from tkinter import ttk -from typing import Optional - -from DEPRECATED_discopop_wizard.classes.Arguments import Arguments -from DEPRECATED_discopop_wizard.classes.Console import Console -from DEPRECATED_discopop_wizard.classes.ProfilingContainer import ProfilingContainer -from DEPRECATED_discopop_wizard.classes.Settings import Settings, load_from_config_file -from DEPRECATED_discopop_wizard.classes.TKVarStorage import TKVarStorage -from DEPRECATED_discopop_wizard.screens.main import MainScreen - -# todo add command line option to list available run configurations -# todo add command line option to execute run configuration (by name) -from DEPRECATED_discopop_wizard.screens.settings import show_settings_screen -from DEPRECATED_discopop_wizard.utils import get_platform, Platform - - -def main(arguments: Arguments): - print("starting DiscoPoP Wizard...\n") - source_dir = dirname(os.path.abspath(__file__)) # source_dir: discopop/discopop_wizard - config_dir = os.path.join(source_dir, ".config") - - # check if config exists, if not, initialize config folder and files - if not os.path.exists(config_dir): - os.mkdir(config_dir) - if not os.path.exists(os.path.join(config_dir, "execution_configurations")): - os.mkdir(os.path.join(config_dir, "execution_configurations")) - - # check if SETTINGS file exists. if not, create it. - if not os.path.exists(os.path.join(config_dir, "SETTINGS.txt")): - with open(os.path.join(config_dir, "SETTINGS.txt"), "w+"): - pass - - wizard = DiscoPoPConfigurationWizard(config_dir, arguments) - print() - - -class ConsoleStyles(IntEnum): - NORMAL = 1 - WARNING = 2 - ERROR = 3 - - -class DiscoPoPConfigurationWizard(object): - arguments: Arguments - settings: Settings - window: tk.Tk - window_frame: tk.Frame - config_dir: str - menubar: tk.Menu - profiling_container: Optional[ProfilingContainer] = None - tk_var_storage: TKVarStorage - - ## font styles - style_font_bold: str = "Helvetica 12 bold" - style_font_bold_small: str = "Helvetica 10 bold" - - def __init__(self, config_dir: str, arguments: Arguments, headless_mode: bool = False): - self.arguments = arguments - self.config_dir = config_dir - # check if settings exist - if os.stat(os.path.join(config_dir, "SETTINGS.txt")).st_size == 0: - # no settings exist - prompt_result = messagebox.askyesno( - "DiscoPoP Wizard", - "Do you want to make use of a docker container for the profiling?", - ) - if not prompt_result: - # ask user for path to discopop_build and go/bin directory - discopop_build_dir = filedialog.askdirectory(title="Select DiscoPoP build folder") - go_bin_dir = filedialog.askdirectory(title="Select go/bin folder (Go installation)") - else: - discopop_build_dir = "" - go_bin_dir = "" - self.settings = Settings( - use_docker_container=prompt_result, - discopop_build_dir=discopop_build_dir, - go_bin_dir=go_bin_dir, - ) - else: - # load settings - self.settings = load_from_config_file(config_dir) - if not headless_mode: - self.initialize_screen(config_dir) - - def initialize_screen(self, config_dir: str): - self.window = tk.Tk() - self.window.title("DiscoPoP Wizard") - - # enable closing by pressing CTRL+C in the command line or the interface - def handler(event): - self.window.destroy() - print("caught ^C") - - def check(): - self.window.after(500, check) - - signal.signal(signal.SIGINT, lambda x, y: print("terminal ^C") or handler(None)) - self.window.after(500, check) - # self.window.bind_all('', handler) # uncomment to close with CTRL+C from interface - - # load window icon - try: - photo = tk.PhotoImage( - file=os.path.join( - str(pathlib.Path(__file__).parent.resolve()), - "assets", - "icons", - "discoPoP_128x128.png", - ) - ) - self.window.iconphoto(False, photo) - except tk.TclError: - warnings.warn("Loading the window icon was not successful.") - - # set window to full screen - if get_platform() in (Platform.OSX, Platform.WINDOWS): - self.window.state("zoomed") - else: - self.window.attributes("-zoomed", True) - self.window.columnconfigure(1, weight=1) - self.window.rowconfigure(1, weight=1) - paned_window = ttk.PanedWindow(self.window, orient=tk.VERTICAL) - paned_window.pack(fill=tk.BOTH, expand=True) - - # create content frame - self.window_frame = tk.Frame(paned_window) - paned_window.add(self.window_frame, weight=5) - self.window_frame.columnconfigure(1, weight=1) - self.window_frame.rowconfigure(1, weight=1) - - # create menu bar - self.menubar = tk.Menu(self.window) - self.window.config(menu=self.menubar) - - # create console frame - self.console_frame = tk.Frame(paned_window) - paned_window.add(self.console_frame, weight=0) - self.console_frame.columnconfigure(1, weight=1) - self.console_frame.rowconfigure(1, weight=1) - self.console = Console(self.console_frame) - - # create TKVarStorage - self.tk_var_storage = TKVarStorage(self) - - MainScreen(self, self.window_frame) - - # show settings screen if first start - if not self.settings.initialized: - show_settings_screen(self) - else: - # save settings - self.settings.save_to_file(self.config_dir) - - self.window.mainloop() - - # close DiscoPoP profiling profiling_container before exiting the application - if self.profiling_container is not None: - self.profiling_container.stop() - - def close_frame_contents(self): - # close current frame contents - for c in self.window_frame.winfo_children(): - c.destroy() - # create empty menu bar - self.menubar.destroy() - self.menubar = tk.Menu(self.window) - self.window.config(menu=self.menubar) - - def show_main_screen(self): - self.close_frame_contents() - MainScreen(self, self.window_frame) diff --git a/discopop_library/discopop_optimizer/gui/presentation/ChoiceDetails.py b/discopop_library/discopop_optimizer/gui/presentation/ChoiceDetails.py index d17e80ec1..540db72f2 100644 --- a/discopop_library/discopop_optimizer/gui/presentation/ChoiceDetails.py +++ b/discopop_library/discopop_optimizer/gui/presentation/ChoiceDetails.py @@ -13,7 +13,7 @@ from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel from discopop_library.discopop_optimizer.gui.widgets.ScrollableFrame import ScrollableFrameWidget from discopop_library.discopop_optimizer.utilities.simple_utilities import data_at -from DEPRECATED_discopop_wizard.screens.widgets.ScrollableText import ScrollableTextWidget +from discopop_library.discopop_optimizer.gui.widgets.ScrollableText import ScrollableTextWidget def display_choices_for_model(graph: nx.DiGraph, model: CostModel, window_title: Optional[str] = None) -> None: diff --git a/DEPRECATED_discopop_wizard/screens/widgets/ScrollableText.py b/discopop_library/discopop_optimizer/gui/widgets/ScrollableText.py similarity index 100% rename from DEPRECATED_discopop_wizard/screens/widgets/ScrollableText.py rename to discopop_library/discopop_optimizer/gui/widgets/ScrollableText.py diff --git a/setup.py b/setup.py index 413ceba19..f08890c6d 100644 --- a/setup.py +++ b/setup.py @@ -58,8 +58,6 @@ entry_points={ "console_scripts": [ "discopop_explorer=discopop_explorer.__main__:main", - "DEPRECATED_discopop_profiler=DEPRECATED_discopop_profiler.__main__:main", - "DEPRECATED_discopop_wizard=DEPRECATED_discopop_wizard.__main__:main", "discopop_optimizer=discopop_library.discopop_optimizer.__main__:main", "discopop_patch_generator=discopop_library.PatchGenerator.__main__:main", "discopop_patch_applicator=discopop_library.PatchApplicator.__main__:main", From f71955a1a6efd961a3df95725e09da66fa146738 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 24 Jul 2024 12:42:51 +0200 Subject: [PATCH 035/105] fix(profiler)[hybrid]: potential segfault --- DiscoPoP/llvm_hooks/runOnFunction.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/DiscoPoP/llvm_hooks/runOnFunction.cpp b/DiscoPoP/llvm_hooks/runOnFunction.cpp index f85dd0c88..dc4e9bdaa 100644 --- a/DiscoPoP/llvm_hooks/runOnFunction.cpp +++ b/DiscoPoP/llvm_hooks/runOnFunction.cpp @@ -224,11 +224,15 @@ bool DiscoPoP::runOnFunction(Function &F) { // Remove values from locals if dereferenced if (isa(I)) { V = I.getOperand(0); + std::set < Value*> to_be_removed; for (Value *w : staticallyPredictableValues) { if (w == V) { - staticallyPredictableValues.erase(V); + to_be_removed.insert(V); } } + for(Value* w: to_be_removed){ + staticallyPredictableValues.erase(V); + } } } } From d174b2921897711cd9a47efdcd9debfc9dffd870 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Fri, 26 Jul 2024 09:51:47 +0200 Subject: [PATCH 036/105] feat[autotuner]: improved reporting --- .../EmpiricalAutotuning/ArgumentClasses.py | 1 + .../EmpiricalAutotuning/Autotuner.py | 29 ++++++++++++------- .../EmpiricalAutotuning/__main__.py | 2 ++ 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/discopop_library/EmpiricalAutotuning/ArgumentClasses.py b/discopop_library/EmpiricalAutotuning/ArgumentClasses.py index 7392ce682..9b8ecaaf4 100644 --- a/discopop_library/EmpiricalAutotuning/ArgumentClasses.py +++ b/discopop_library/EmpiricalAutotuning/ArgumentClasses.py @@ -20,6 +20,7 @@ class AutotunerArguments(GeneralArguments): project_path: str dot_dp_path: str + skip_cleanup: bool def __post_init__(self) -> None: self.__validate() diff --git a/discopop_library/EmpiricalAutotuning/Autotuner.py b/discopop_library/EmpiricalAutotuning/Autotuner.py index 68cf81246..f674dbd46 100644 --- a/discopop_library/EmpiricalAutotuning/Autotuner.py +++ b/discopop_library/EmpiricalAutotuning/Autotuner.py @@ -36,7 +36,7 @@ def get_unique_configuration_id() -> int: def run(arguments: AutotunerArguments) -> None: logger.info("Starting discopop autotuner.") - debug_stats: List[Tuple[List[SUGGESTION_ID], float]] = [] + debug_stats: List[Tuple[List[SUGGESTION_ID], float, int, str]] = [] statistics_graph = StatisticsGraph() statistics_step_num = 0 @@ -49,7 +49,7 @@ def run(arguments: AutotunerArguments) -> None: shape=NodeShape.BOX, ) timeout_after = cast(ExecutionResult, reference_configuration.execution_result).runtime * 2 - debug_stats.append(([], cast(ExecutionResult, reference_configuration.execution_result).runtime)) + debug_stats.append(([], cast(ExecutionResult, reference_configuration.execution_result).runtime, cast(ExecutionResult, reference_configuration.execution_result).return_code, reference_configuration.root_path)) # load hotspots hsl_arguments = HotspotLoaderArguments( @@ -114,13 +114,15 @@ def run(arguments: AutotunerArguments) -> None: color=tmp_config.get_statistics_graph_color(), ) # only consider valid code + debug_stats.append((current_config, cast(ExecutionResult, tmp_config.execution_result).runtime, cast(ExecutionResult, tmp_config.execution_result).return_code, tmp_config.root_path)) if ( cast(ExecutionResult, tmp_config.execution_result).result_valid and cast(ExecutionResult, tmp_config.execution_result).return_code == 0 ): suggestion_effects.append((current_config, tmp_config)) - debug_stats.append((current_config, cast(ExecutionResult, tmp_config.execution_result).runtime)) else: + if arguments.skip_cleanup: + continue # delete invalid code tmp_config.deleteFolder() # add current best configuration for reference / to detect "no suggestions is beneficial" @@ -174,21 +176,28 @@ def run(arguments: AutotunerArguments) -> None: statistics_graph.output() statistics_step_num += 1 # cleanup other configurations (excluding original version) - logger.debug("Cleanup:") - for _, config in sorted_suggestion_effects: - if config.root_path == reference_configuration.root_path: - continue - config.deleteFolder() + if not arguments.skip_cleanup: + logger.debug("Cleanup:") + for _, config in sorted_suggestion_effects: + if config.root_path == reference_configuration.root_path: + continue + config.deleteFolder() # continue with the next loop # show debug stats stats_str = "Configuration measurements:\n" - stats_str += "[time]\t[applied suggestions]\n" + stats_str += "[time]\t[applied suggestions]\t[return code]\t[path]\n" for stats in sorted(debug_stats, key=lambda x: x[1], reverse=True): - stats_str += str(round(stats[1], 3)) + "s" + "\t" + str(stats[0]) + "\n" + stats_str += str(round(stats[1], 3)) + "s" + "\t" + str(stats[0]) + "\t" + str(stats[2]) + "\t" + str(stats[3]) + "\n" logger.info(stats_str) + # export measurements for pdf creation + with open("measurements.csv", "w+") as f: + f.write("ID; time; return_code;\n") + for stats in sorted(debug_stats, key=lambda x: x[1], reverse=True): + f.write(str(stats[0]) + "; " + str(round(stats[1], 3)) + "; " + str(stats[2]) + ";" + "\n") + # calculate result statistics speedup = ( cast(ExecutionResult, reference_configuration.execution_result).runtime diff --git a/discopop_library/EmpiricalAutotuning/__main__.py b/discopop_library/EmpiricalAutotuning/__main__.py index ef48f32c9..1ab18a61f 100644 --- a/discopop_library/EmpiricalAutotuning/__main__.py +++ b/discopop_library/EmpiricalAutotuning/__main__.py @@ -27,6 +27,7 @@ def parse_args() -> AutotunerArguments: DP_EXECUTE.sh may return not 0, if either the execution or validation of the result failed. \ A third script DP_VALIDATE.sh might be added to add a validation step, where return code 0 is interpreted as a success, i.e. a valid result.") parser.add_argument("--dot-dp-path", type=str, default=os.path.join(os.getcwd(), ".discopop"), help="Path to the .discopop folder.") + parser.add_argument("--skip-cleanup", action="store_true", help="disable the deletion of created code variants. May require a lot of disk space." ) # fmt: on arguments = parser.parse_args() @@ -36,6 +37,7 @@ def parse_args() -> AutotunerArguments: write_log=arguments.write_log, project_path=arguments.project_path, dot_dp_path=arguments.dot_dp_path, + skip_cleanup=arguments.skip_cleanup ) From 4312d321ecf35d5fba32e757b6817fb58a80daec Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Fri, 26 Jul 2024 09:52:15 +0200 Subject: [PATCH 037/105] fix[explorer](variable classification): prevent duplicates --- discopop_explorer/utils.py | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index 02e8ca60b..122a2c46a 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -763,22 +763,23 @@ def classify_loop_variables( # check if metadata suggests, that index accesses are not problematic wrt. parallelization metadata_safe_index_accesses.append(var) - if loop.start_position() == "1:281": - pass # modify classifications first_private, private, last_private, shared, reduction = __modify_classifications( first_private, private, last_private, shared, reduction, metadata_safe_index_accesses ) - if loop.start_position() == "1:281": - pass # merge classifications first_private, private, last_private, shared, reduction = __merge_classifications( first_private, private, last_private, shared, reduction ) - if loop.start_position() == "1:281": - pass + # remove duplicates + first_private = __remove_duplicate_variables(first_private) + private = __remove_duplicate_variables(private) + last_private = __remove_duplicate_variables(last_private) + shared = __remove_duplicate_variables(shared) + reduction = __remove_duplicate_variables(reduction) + # return first_private, private, last_private, shared, reduction return ( sorted(first_private), @@ -788,6 +789,18 @@ def classify_loop_variables( sorted(reduction), ) +def __remove_duplicate_variables(vars: List[Variable]) ->List[Variable]: + buffer : List[str] = [] + vars_wo_duplicates : List[Variable] = [] + for var in vars: + if var.name + var.defLine not in buffer: + vars_wo_duplicates.append(var) + buffer.append(var.name + var.defLine) + else: + # duplicate found + continue + return vars_wo_duplicates + def var_declared_in_subtree(var: Variable, sub: list[CUNode]) -> bool: var_file_id = int(var.defLine.split(":")[0]) From c5e3458278fee95c1616e8e0f2178f978f56c5d1 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Fri, 26 Jul 2024 10:13:53 +0200 Subject: [PATCH 038/105] fix: formatting --- discopop_explorer/utils.py | 7 +++--- .../EmpiricalAutotuning/Autotuner.py | 22 ++++++++++++++++--- .../EmpiricalAutotuning/__main__.py | 2 +- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index 122a2c46a..1bbfc176e 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -789,9 +789,10 @@ def classify_loop_variables( sorted(reduction), ) -def __remove_duplicate_variables(vars: List[Variable]) ->List[Variable]: - buffer : List[str] = [] - vars_wo_duplicates : List[Variable] = [] + +def __remove_duplicate_variables(vars: List[Variable]) -> List[Variable]: + buffer: List[str] = [] + vars_wo_duplicates: List[Variable] = [] for var in vars: if var.name + var.defLine not in buffer: vars_wo_duplicates.append(var) diff --git a/discopop_library/EmpiricalAutotuning/Autotuner.py b/discopop_library/EmpiricalAutotuning/Autotuner.py index f674dbd46..491a1fc76 100644 --- a/discopop_library/EmpiricalAutotuning/Autotuner.py +++ b/discopop_library/EmpiricalAutotuning/Autotuner.py @@ -49,7 +49,14 @@ def run(arguments: AutotunerArguments) -> None: shape=NodeShape.BOX, ) timeout_after = cast(ExecutionResult, reference_configuration.execution_result).runtime * 2 - debug_stats.append(([], cast(ExecutionResult, reference_configuration.execution_result).runtime, cast(ExecutionResult, reference_configuration.execution_result).return_code, reference_configuration.root_path)) + debug_stats.append( + ( + [], + cast(ExecutionResult, reference_configuration.execution_result).runtime, + cast(ExecutionResult, reference_configuration.execution_result).return_code, + reference_configuration.root_path, + ) + ) # load hotspots hsl_arguments = HotspotLoaderArguments( @@ -114,7 +121,14 @@ def run(arguments: AutotunerArguments) -> None: color=tmp_config.get_statistics_graph_color(), ) # only consider valid code - debug_stats.append((current_config, cast(ExecutionResult, tmp_config.execution_result).runtime, cast(ExecutionResult, tmp_config.execution_result).return_code, tmp_config.root_path)) + debug_stats.append( + ( + current_config, + cast(ExecutionResult, tmp_config.execution_result).runtime, + cast(ExecutionResult, tmp_config.execution_result).return_code, + tmp_config.root_path, + ) + ) if ( cast(ExecutionResult, tmp_config.execution_result).result_valid and cast(ExecutionResult, tmp_config.execution_result).return_code == 0 @@ -189,7 +203,9 @@ def run(arguments: AutotunerArguments) -> None: stats_str = "Configuration measurements:\n" stats_str += "[time]\t[applied suggestions]\t[return code]\t[path]\n" for stats in sorted(debug_stats, key=lambda x: x[1], reverse=True): - stats_str += str(round(stats[1], 3)) + "s" + "\t" + str(stats[0]) + "\t" + str(stats[2]) + "\t" + str(stats[3]) + "\n" + stats_str += ( + str(round(stats[1], 3)) + "s" + "\t" + str(stats[0]) + "\t" + str(stats[2]) + "\t" + str(stats[3]) + "\n" + ) logger.info(stats_str) # export measurements for pdf creation diff --git a/discopop_library/EmpiricalAutotuning/__main__.py b/discopop_library/EmpiricalAutotuning/__main__.py index 1ab18a61f..166e85d1d 100644 --- a/discopop_library/EmpiricalAutotuning/__main__.py +++ b/discopop_library/EmpiricalAutotuning/__main__.py @@ -37,7 +37,7 @@ def parse_args() -> AutotunerArguments: write_log=arguments.write_log, project_path=arguments.project_path, dot_dp_path=arguments.dot_dp_path, - skip_cleanup=arguments.skip_cleanup + skip_cleanup=arguments.skip_cleanup, ) From 2c2ca03934beafe69ad67aece3b07abc1e5acd2f Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Thu, 18 Jul 2024 11:12:24 +0200 Subject: [PATCH 039/105] fix(explorer): incorrect variable clauses due to pass by value arguments --- .../pattern_detectors/reduction_detector.py | 1 - discopop_explorer/utils.py | 13 +++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index 12706cd5d..9fced17fa 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -121,7 +121,6 @@ def __check_node(param_tuple: LoopNode) -> List[ReductionInfo]: def __detect_reduction(pet: PEGraphX, root: LoopNode) -> bool: """Detects reduction pattern in loop - :param pet: PET graph :param root: the loop node :return: true if is reduction loop diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index 1bbfc176e..35a8542ec 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -619,11 +619,24 @@ def get_child_loops(pet: PEGraphX, node: Node) -> Tuple[List[Node], List[Node]]: def get_initialized_memory_regions_in(pet: PEGraphX, cu_nodes: List[CUNode]) -> Dict[Variable, Set[MemoryRegion]]: initialized_memory_regions: Dict[Variable, Set[MemoryRegion]] = dict() for cu in cu_nodes: + parent_function = pet.get_parent_function(cu) for s, t, d in pet.out_edges(cu.id, EdgeType.DATA): if d.dtype == DepType.INIT and d.memory_region is not None: # get variable object from cu for var in cu.global_vars + cu.local_vars: if var.name == d.var_name: + # ignore pass by value type function arguments + is_passed_by_value = False + if str(parent_function.start_position()) == var.defLine: + for arg in parent_function.args: + if arg.name == var.name: + if "*" not in arg.type: + # found pass by value argument + is_passed_by_value = True + break + if is_passed_by_value: + continue + if var not in initialized_memory_regions: initialized_memory_regions[var] = set() # create entry for initialized variable From 07eb0854175dd856f80935f248a5a9ae04dd3dbe Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Fri, 26 Jul 2024 11:56:49 +0200 Subject: [PATCH 040/105] fix(autotuner): minor reliablity fixes --- discopop_library/EmpiricalAutotuning/Autotuner.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/discopop_library/EmpiricalAutotuning/Autotuner.py b/discopop_library/EmpiricalAutotuning/Autotuner.py index 491a1fc76..d7bec99d8 100644 --- a/discopop_library/EmpiricalAutotuning/Autotuner.py +++ b/discopop_library/EmpiricalAutotuning/Autotuner.py @@ -48,7 +48,7 @@ def run(arguments: AutotunerArguments) -> None: color=reference_configuration.get_statistics_graph_color(), shape=NodeShape.BOX, ) - timeout_after = cast(ExecutionResult, reference_configuration.execution_result).runtime * 2 + timeout_after = max(3.0, cast(ExecutionResult, reference_configuration.execution_result).runtime * 2) debug_stats.append( ( [], @@ -108,7 +108,10 @@ def run(arguments: AutotunerArguments) -> None: continue visited_configurations.append(current_config) tmp_config = reference_configuration.create_copy(get_unique_configuration_id) - tmp_config.apply_suggestions(arguments, current_config) + try: + tmp_config.apply_suggestions(arguments, current_config) + except ValueError: + continue tmp_config.execute(timeout=timeout_after) statistics_graph.add_child( "step " From 9575ba355aa9fda0945f34eaf713f402ef066837 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Mon, 29 Jul 2024 13:26:58 +0200 Subject: [PATCH 041/105] feat[autotuner]: allow absence of hotspot information --- .../EmpiricalAutotuning/ArgumentClasses.py | 2 -- .../EmpiricalAutotuning/Autotuner.py | 20 +++++++++++++++---- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/discopop_library/EmpiricalAutotuning/ArgumentClasses.py b/discopop_library/EmpiricalAutotuning/ArgumentClasses.py index 9b8ecaaf4..4b5d69a5d 100644 --- a/discopop_library/EmpiricalAutotuning/ArgumentClasses.py +++ b/discopop_library/EmpiricalAutotuning/ArgumentClasses.py @@ -42,8 +42,6 @@ def __validate(self) -> None: os.path.join(self.dot_dp_path, "profiler"), os.path.join(self.dot_dp_path, "explorer"), os.path.join(self.dot_dp_path, "patch_generator"), - os.path.join(self.dot_dp_path, "hotspot_detection"), - os.path.join(self.dot_dp_path, "hotspot_detection", "Hotspots.json"), os.path.join(self.dot_dp_path, "line_mapping.json"), ] for file in required_files: diff --git a/discopop_library/EmpiricalAutotuning/Autotuner.py b/discopop_library/EmpiricalAutotuning/Autotuner.py index d7bec99d8..179b3a426 100644 --- a/discopop_library/EmpiricalAutotuning/Autotuner.py +++ b/discopop_library/EmpiricalAutotuning/Autotuner.py @@ -11,6 +11,7 @@ from typing import List, Optional, Set, Tuple, cast import jsonpickle # type: ignore +from discopop_explorer.PEGraphX import LoopNode from discopop_library.EmpiricalAutotuning.ArgumentClasses import AutotunerArguments from discopop_library.EmpiricalAutotuning.Classes.CodeConfiguration import CodeConfiguration from discopop_library.EmpiricalAutotuning.Classes.ExecutionResult import ExecutionResult @@ -18,6 +19,7 @@ from discopop_library.EmpiricalAutotuning.Types import SUGGESTION_ID from discopop_library.EmpiricalAutotuning.utils import get_applicable_suggestion_ids from discopop_library.HostpotLoader.HotspotLoaderArguments import HotspotLoaderArguments +from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType from discopop_library.HostpotLoader.HotspotType import HotspotType from discopop_library.HostpotLoader.hostpot_loader import run as load_hotspots from discopop_library.result_classes.DetectionResult import DetectionResult @@ -75,11 +77,21 @@ def run(arguments: AutotunerArguments) -> None: visited_configurations: List[List[SUGGESTION_ID]] = [] best_suggestion_configuration: Tuple[List[SUGGESTION_ID], CodeConfiguration] = ([], reference_configuration) for hotspot_type in [HotspotType.YES, HotspotType.MAYBE, HotspotType.NO]: - if hotspot_type not in hotspot_information: - continue - # for all loops in descending order by average execution time - loop_tuples = hotspot_information[hotspot_type] + if hotspot_information: + # hotspot information exists + if hotspot_type not in hotspot_information: + continue + # for all loops in descending order by average execution time + loop_tuples = hotspot_information[hotspot_type] + sorted_loop_tuples = sorted(loop_tuples, key=lambda x: x[4], reverse=True) + else: + # no hotspot information was found + # get loop tuples from detection result + loop_nodes = detection_result.pet.all_nodes(type=LoopNode) + loop_tuples = [(l.file_id, l.start_line, HotspotNodeType.LOOP, "", 0.0) for l in loop_nodes] + sorted_loop_tuples = sorted(loop_tuples, key=lambda x: x[4], reverse=True) + for loop_tuple in sorted_loop_tuples: loop_str = ( "" From 4f546171c3a243d9ee5ae198a1f3eb7fb286d32d Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Mon, 29 Jul 2024 13:57:00 +0200 Subject: [PATCH 042/105] feat(build): add flag DP_BRANCH_TRACKING --- CMakeLists.txt | 2 +- DiscoPoP/CMakeLists.txt | 15 ++++++++++++--- DiscoPoP/DiscoPoP.hpp | 4 ---- docs/setup/discopop.md | 2 +- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7931a04c0..b798c087d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,7 +99,7 @@ file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build_config.py" "DP_CALLTREE_PROFILING_METADATA_CUTOFF=\"${DP_CALLTREE_PROFILING_METADATA_CUTOFF}\"\n") file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build_config.py" "DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY=\"${DP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY}\"\n") file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build_config.py" "DP_MEMORY_REGION_DEALIASING=\"${DP_MEMORY_REGION_DEALIASING}\"\n") - +file(APPEND "${DiscoPoP_SOURCE_DIR}/discopop_library/ConfigProvider/assets/build_config.py" "DP_BRANCH_TRACKING=\"${DP_BRANCH_TRACKING}\"\n") # print DiscoPoP configuration diff --git a/DiscoPoP/CMakeLists.txt b/DiscoPoP/CMakeLists.txt index 941b755cc..99606ec37 100644 --- a/DiscoPoP/CMakeLists.txt +++ b/DiscoPoP/CMakeLists.txt @@ -38,7 +38,7 @@ add_llvm_library(LLVMDiscoPoP MODULE initialization/initializeCUIDCounter.cpp initialization/initializeBBDepCounter.cpp - + llvm_hooks/doInitialization.cpp llvm_hooks/doFinalization.cpp llvm_hooks/runOnBasicBlock.cpp @@ -51,7 +51,7 @@ add_llvm_library(LLVMDiscoPoP MODULE dp_reduction/determine_variable_type.cpp dp_reduction/CFA.cpp dp_reduction/get_var.cpp - dp_reduction/get_reduction_instr.cpp + dp_reduction/get_reduction_instr.cpp dp_reduction/utils.cpp dp_reduction/insert_functions.cpp @@ -79,4 +79,13 @@ if(DEFINED DP_HYBRID_PROFILING) else() target_compile_definitions(LLVMDiscoPoP PUBLIC DP_HYBRID_PROFILING=1) endif() -# end of compiler flags \ No newline at end of file + +if(DEFINED DP_BRANCH_TRACKING) + target_compile_definitions(LLVMDiscoPoP PUBLIC DP_BRANCH_TRACKING=${DP_BRANCH_TRACKING}) + if(NOT ${DP_BRANCH_TRACKING} EQUAL 0) + message(STATUS "WARNING: DiscoPoP configuration: DP_BRANCH_TRACKING enabled. Reduces profiling speed.") + endif() +else() + target_compile_definitions(LLVMDiscoPoP PUBLIC DP_BRANCH_TRACKING=0) +endif() +# end of compiler flags diff --git a/DiscoPoP/DiscoPoP.hpp b/DiscoPoP/DiscoPoP.hpp index d79438360..896398b09 100644 --- a/DiscoPoP/DiscoPoP.hpp +++ b/DiscoPoP/DiscoPoP.hpp @@ -72,10 +72,6 @@ #define ClCheckLoopPar true #define DumpToDot false -#define DP_BRANCH_TRACKING \ - true // toggles the creation of instrumentation calls for tracking taken - // branches. Required by the graph pruning step of the DiscoPoP - // optimizer. #define DP_DEBUG false #define DP_VERBOSE false // prints warning messages #define DP_hybrid_DEBUG false diff --git a/docs/setup/discopop.md b/docs/setup/discopop.md index 604e72acd..b16389381 100644 --- a/docs/setup/discopop.md +++ b/docs/setup/discopop.md @@ -37,7 +37,7 @@ where `` can consist of any combination of the following flags and - `-DDP_CALLTREE_PROFILING_METADATA_CUTOFF=` – Set a cutoff amount of vitis per basic block for dependency metadata calculation. Set `0` to disable cutoff. Default: `50000`. - `-DDP_CALLTREE_PROFILING_METADATA_CUTOFF_IGNORE_PROBABILITY=[0-1000]` – Enable or disable probablistic cutoff. Ignores cutoff with a configurable probability. Set `0` to disable probabilistic cutoff. Set `25` for a probability of 2.5% etc. - `-DDP_MEMORY_REGION_DEALIASING=[0|1]`: Enable or disable the generation of dependency de-aliasing information. Reduces potential false positive parallelization suggestions, but increases the profiling overhead. - +- `-DDP_BRANCH_TRACKING=[0|1]`: Toggles the creation of instrumentation calls for tracking taken branches. Required by the graph pruning step of the DiscoPoP optimizer. Disabled by default. #### Development and debugging - `-DDP_RTLIB_VERBOSE=[0|1]` – Enable verbose output during profiling. From 6963f2467cb8d315785e5bb4b4ef78d3e27e4867 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Mon, 29 Jul 2024 16:12:01 +0200 Subject: [PATCH 043/105] fix(profiler): potential segmentation fault due to regex recursion --- rtlib/injected_functions/dp_add_bb_deps.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/rtlib/injected_functions/dp_add_bb_deps.cpp b/rtlib/injected_functions/dp_add_bb_deps.cpp index 9e6efb428..84a3e1ddd 100644 --- a/rtlib/injected_functions/dp_add_bb_deps.cpp +++ b/rtlib/injected_functions/dp_add_bb_deps.cpp @@ -23,6 +23,7 @@ #include #include #include +#include namespace __dp { @@ -46,16 +47,15 @@ void __dp_add_bb_deps(char *depStringPtr) { std::string depString(depStringPtr); std::regex r0("[^\\/]+"), r1("[^=]+"), r2("[^,]+"), r3("[0-9]+:[0-9]+"), r4("(INIT|(R|W)A(R|W)).*"); - std::smatch res0, res1, res2, res3; + std::smatch res1, res2, res3; - while (regex_search(depString, res0, r0)) { - std::string s(res0[0]); + std::vector strs; + boost::split(strs, depString, boost::is_any_of("/")); - regex_search(s, res1, r1); + for(string substring : strs) { + regex_search(substring, res1, r1); std::string cond(res1[0]); - if (bbList->find(stoi(cond)) == bbList->end()) { - depString = res0.suffix(); continue; } @@ -74,7 +74,6 @@ void __dp_add_bb_deps(char *depStringPtr) { (*outPutDeps)[k].insert(v); line = res2.suffix(); } - depString = res0.suffix(); } } // End HA From 76fa24f8c4b8083521d2e6f0f0a8ec0b2bd91c4c Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Mon, 29 Jul 2024 16:58:47 +0200 Subject: [PATCH 044/105] fix(profiler): prevent potential invalid_argument error --- rtlib/injected_functions/dp_add_bb_deps.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/rtlib/injected_functions/dp_add_bb_deps.cpp b/rtlib/injected_functions/dp_add_bb_deps.cpp index 84a3e1ddd..2a3e1a998 100644 --- a/rtlib/injected_functions/dp_add_bb_deps.cpp +++ b/rtlib/injected_functions/dp_add_bb_deps.cpp @@ -55,10 +55,14 @@ void __dp_add_bb_deps(char *depStringPtr) { for(string substring : strs) { regex_search(substring, res1, r1); std::string cond(res1[0]); + + if(cond.length() == 0){ + // skip invalid entry + continue; + } if (bbList->find(stoi(cond)) == bbList->end()) { continue; } - std::string line(res1.suffix()); line.erase(0, 1); while (regex_search(line, res2, r2)) { From 3c0b8d30695209cbde37530ac3ff9373728ff59e Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 30 Jul 2024 13:52:53 +0200 Subject: [PATCH 045/105] feat(autotuner): print only sequential and best measurement --- .../EmpiricalAutotuning/Autotuner.py | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/discopop_library/EmpiricalAutotuning/Autotuner.py b/discopop_library/EmpiricalAutotuning/Autotuner.py index 179b3a426..374497c3b 100644 --- a/discopop_library/EmpiricalAutotuning/Autotuner.py +++ b/discopop_library/EmpiricalAutotuning/Autotuner.py @@ -224,10 +224,24 @@ def run(arguments: AutotunerArguments) -> None: logger.info(stats_str) # export measurements for pdf creation - with open("measurements.csv", "w+") as f: - f.write("ID; time; return_code;\n") - for stats in sorted(debug_stats, key=lambda x: x[1], reverse=True): - f.write(str(stats[0]) + "; " + str(round(stats[1], 3)) + "; " + str(stats[2]) + ";" + "\n") + if False: # export all measurements + with open("measurements.csv", "w+") as f: + f.write("ID; time; return_code;\n") + for stats in sorted(debug_stats, key=lambda x: x[1], reverse=True): + f.write(str(stats[0]) + "; " + str(round(stats[1], 3)) + "; " + str(stats[2]) + ";" + "\n") + else: # export only sequential and best measurement + with open("measurements.csv", "w+") as f: + f.write("ID; time; return_code;\n") + # write sequential measurement + for stats in sorted(debug_stats, key=lambda x: x[1], reverse=True): + if str(stats[0]) == "[]": + f.write(str(stats[0]) + "; " + str(round(stats[1], 3)) + "; " + str(stats[2]) + ";" + "\n") + # write best measurement + for stats in sorted(debug_stats, key=lambda x: x[1], reverse=False): + if str(stats[2]) != "0": + continue + f.write(str(stats[0]) + "; " + str(round(stats[1], 3)) + "; " + str(stats[2]) + ";" + "\n") + break # calculate result statistics speedup = ( From acff8790ac51f2a19cfd8d1e0d604c0c9cc7e5ac Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 30 Jul 2024 16:08:00 +0200 Subject: [PATCH 046/105] refactor: EdgeType --- discopop_explorer/PEGraphX.py | 33 +++++++++---------- discopop_explorer/enums/EdgeType.py | 19 +++++++++++ discopop_explorer/enums/__init__.py | 0 discopop_explorer/generate_Data_CUInst.py | 2 +- discopop_explorer/pattern_detection.py | 3 +- .../CombinedGPURegions.py | 27 +++++++-------- .../combined_gpu_patterns/step_1.py | 3 +- .../combined_gpu_patterns/step_2.py | 2 +- .../combined_gpu_patterns/step_3.py | 3 +- .../combined_gpu_patterns/step_4.py | 2 +- .../combined_gpu_patterns/step_6.py | 2 +- .../combined_gpu_patterns/utilities.py | 2 +- .../pattern_detectors/do_all_detector.py | 2 +- .../geometric_decomposition_detector.py | 3 +- .../pattern_detectors/pipeline_detector.py | 2 +- .../pattern_detectors/reduction_detector.py | 2 +- .../simple_gpu_patterns/GPURegions.py | 2 +- .../task_parallelism/filter.py | 3 +- .../task_parallelism/postprocessor.py | 3 +- .../task_parallelism/suggesters/auxiliary.py | 3 +- .../task_parallelism/suggesters/barriers.py | 3 +- .../suggesters/data_sharing_clauses.py | 3 +- .../suggesters/dependency_clauses.py | 2 +- .../task_parallelism/suggesters/tasks.py | 2 +- .../task_parallelism/tp_utils.py | 2 +- discopop_explorer/plugins/pipeline.py | 3 +- discopop_explorer/utils.py | 13 ++------ .../DataTransfers/DataTransfers.py | 3 +- .../PETParser/DataAccesses/FromCUs.py | 3 +- .../discopop_optimizer/PETParser/PETParser.py | 2 +- .../classes/nodes/Workload.py | 3 +- .../optimization/validation.py | 3 +- 32 files changed, 92 insertions(+), 68 deletions(-) create mode 100644 discopop_explorer/enums/EdgeType.py create mode 100644 discopop_explorer/enums/__init__.py diff --git a/discopop_explorer/PEGraphX.py b/discopop_explorer/PEGraphX.py index d7840b6b2..fb881e3ea 100644 --- a/discopop_explorer/PEGraphX.py +++ b/discopop_explorer/PEGraphX.py @@ -21,6 +21,7 @@ from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType from discopop_library.HostpotLoader.HotspotType import HotspotType # type:ignore +from .enums.EdgeType import EdgeType from .parser import LoopData, readlineToCUIdMap, writelineToCUIdMap, DependenceItem from .variable import Variable @@ -55,14 +56,6 @@ def parse_id(node_id: str) -> Tuple[int, int]: return int(split[0]), int(split[1]) -class EdgeType(Enum): - CHILD = 0 - SUCCESSOR = 1 - DATA = 2 - CALLSNODE = 3 - PRODUCE_CONSUME = 4 - - class DepType(Enum): RAW = 0 WAR = 1 @@ -173,9 +166,9 @@ class Node: end_line: int type: NodeType name: str - parent_function_id: Optional[NodeID] = ( - None # metadata to speedup some calculations (TODO FunctionNodes have themselves as parent) - ) + parent_function_id: Optional[ + NodeID + ] = None # metadata to speedup some calculations (TODO FunctionNodes have themselves as parent) workload: Optional[int] = None # properties of CU Nodes @@ -1008,10 +1001,12 @@ def node_at(self, node_id: NodeID) -> Node: NodeT = TypeVar("NodeT", bound=Node) @overload - def all_nodes(self) -> List[Node]: ... + def all_nodes(self) -> List[Node]: + ... @overload - def all_nodes(self, type: Union[Type[NodeT], Tuple[Type[NodeT], ...]]) -> List[NodeT]: ... + def all_nodes(self, type: Union[Type[NodeT], Tuple[Type[NodeT], ...]]) -> List[NodeT]: + ... def all_nodes(self, type: Any = Node) -> List[NodeT]: """List of all nodes of specified type @@ -1054,10 +1049,12 @@ def in_edges( return [t for t in self.g.in_edges(node_id, data="data") if t[2].etype == etype] @overload - def subtree_of_type(self, root: Node) -> List[Node]: ... + def subtree_of_type(self, root: Node) -> List[Node]: + ... @overload - def subtree_of_type(self, root: Node, type: Union[Type[NodeT], Tuple[Type[NodeT], ...]]) -> List[NodeT]: ... + def subtree_of_type(self, root: Node, type: Union[Type[NodeT], Tuple[Type[NodeT], ...]]) -> List[NodeT]: + ... def subtree_of_type(self, root: Node, type: Any = Node) -> List[NodeT]: """Gets all nodes in subtree of specified type including root @@ -1069,12 +1066,14 @@ def subtree_of_type(self, root: Node, type: Any = Node) -> List[NodeT]: return self.subtree_of_type_rec(root, set(), type) @overload - def subtree_of_type_rec(self, root: Node, visited: Set[Node]) -> List[Node]: ... + def subtree_of_type_rec(self, root: Node, visited: Set[Node]) -> List[Node]: + ... @overload def subtree_of_type_rec( self, root: Node, visited: Set[Node], type: Union[Type[NodeT], Tuple[Type[NodeT], ...]] - ) -> List[NodeT]: ... + ) -> List[NodeT]: + ... def subtree_of_type_rec(self, root: Node, visited: Set[Node], type: Any = Node) -> List[NodeT]: """recursive helper function for subtree_of_type""" diff --git a/discopop_explorer/enums/EdgeType.py b/discopop_explorer/enums/EdgeType.py new file mode 100644 index 000000000..13968d049 --- /dev/null +++ b/discopop_explorer/enums/EdgeType.py @@ -0,0 +1,19 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from __future__ import annotations + +from enum import Enum + + +class EdgeType(Enum): + CHILD = 0 + SUCCESSOR = 1 + DATA = 2 + CALLSNODE = 3 + PRODUCE_CONSUME = 4 diff --git a/discopop_explorer/enums/__init__.py b/discopop_explorer/enums/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/discopop_explorer/generate_Data_CUInst.py b/discopop_explorer/generate_Data_CUInst.py index cb211aa27..6c9b7bd5b 100644 --- a/discopop_explorer/generate_Data_CUInst.py +++ b/discopop_explorer/generate_Data_CUInst.py @@ -18,8 +18,8 @@ PEGraphX, Node, DepType, - EdgeType, ) +from .enums.EdgeType import EdgeType from .parser import parse_inputs diff --git a/discopop_explorer/pattern_detection.py b/discopop_explorer/pattern_detection.py index e06fae48a..2190baf80 100644 --- a/discopop_explorer/pattern_detection.py +++ b/discopop_explorer/pattern_detection.py @@ -28,7 +28,8 @@ ) from discopop_library.discopop_optimizer.utilities.MOGUtilities import get_nodes_from_cu_id from discopop_library.result_classes.DetectionResult import DetectionResult -from .PEGraphX import DummyNode, LoopNode, NodeID, PEGraphX, EdgeType +from .PEGraphX import DummyNode, LoopNode, NodeID, PEGraphX +from .enums.EdgeType import EdgeType from .pattern_detectors.do_all_detector import DoAllInfo, run_detection as detect_do_all from .pattern_detectors.geometric_decomposition_detector import run_detection as detect_gd from .pattern_detectors.pipeline_detector import run_detection as detect_pipeline diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py index a73feae8b..e4281505d 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py @@ -8,7 +8,8 @@ import sys from typing import List, Tuple, Dict, Set, cast -from discopop_explorer.PEGraphX import EdgeType, CUNode, PEGraphX, NodeID, MemoryRegion +from discopop_explorer.PEGraphX import CUNode, PEGraphX, NodeID, MemoryRegion +from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, @@ -128,9 +129,9 @@ def __init__(self, pet: PEGraphX, contained_regions: List[GPURegionInfo], projec ) = get_written_and_read_memory_regions_by_cu(self.contained_regions, pet) # get memory region and variable associations for each CU - cu_and_variable_to_memory_regions: Dict[NodeID, Dict[VarName, Set[MemoryRegion]]] = ( - get_cu_and_varname_to_memory_regions(self.contained_regions, pet, written_memory_regions_by_cu) - ) + cu_and_variable_to_memory_regions: Dict[ + NodeID, Dict[VarName, Set[MemoryRegion]] + ] = get_cu_and_varname_to_memory_regions(self.contained_regions, pet, written_memory_regions_by_cu) print("WRITTEN MEMORY REGIONS BY CU: ", file=sys.stderr) print(written_memory_regions_by_cu, file=sys.stderr) @@ -141,9 +142,9 @@ def __init__(self, pet: PEGraphX, contained_regions: List[GPURegionInfo], projec print(file=sys.stderr) # get memory regions to cus and variables names - memory_regions_to_cus_and_variables: Dict[MemoryRegion, Dict[NodeID, Set[VarName]]] = ( - get_memory_region_to_cu_and_variables_dict(cu_and_variable_to_memory_regions) - ) + memory_regions_to_cus_and_variables: Dict[ + MemoryRegion, Dict[NodeID, Set[VarName]] + ] = get_memory_region_to_cu_and_variables_dict(cu_and_variable_to_memory_regions) print("MEMORY REGIONS TO CUS AND VARIABLES:", file=sys.stderr) print(memory_regions_to_cus_and_variables, file=sys.stderr) print(file=sys.stderr) @@ -155,9 +156,9 @@ def __init__(self, pet: PEGraphX, contained_regions: List[GPURegionInfo], projec print(file=sys.stderr) # extend device liveness with memory regions - device_liveness_plus_memory_regions: Dict[VarName, List[Tuple[NodeID, Set[MemoryRegion]]]] = ( - add_memory_regions_to_device_liveness(live_device_variables, cu_and_variable_to_memory_regions) - ) + device_liveness_plus_memory_regions: Dict[ + VarName, List[Tuple[NodeID, Set[MemoryRegion]]] + ] = add_memory_regions_to_device_liveness(live_device_variables, cu_and_variable_to_memory_regions) # ### STEP 2.2: CALCULATE LIVE DATA BY PROPAGATING MEMORY REGIONS AND EXTENDING LIFESPAN @@ -257,9 +258,9 @@ def __init__(self, pet: PEGraphX, contained_regions: List[GPURegionInfo], projec # ### STEP 5: CONVERT MEMORY REGIONS IN UPDATES TO VARIABLE NAMES # propagate memory region to variable name associations within function body - memory_regions_to_functions_and_variables: Dict[MemoryRegion, Dict[NodeID, Set[VarName]]] = ( - propagate_variable_name_associations(pet, memory_regions_to_cus_and_variables) - ) + memory_regions_to_functions_and_variables: Dict[ + MemoryRegion, Dict[NodeID, Set[VarName]] + ] = propagate_variable_name_associations(pet, memory_regions_to_cus_and_variables) print("MEMORY REGIONS TO FUNCTIONS AND VARIABLES:", file=sys.stderr) print(memory_regions_to_functions_and_variables, file=sys.stderr) print(file=sys.stderr) diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py index 8de5648e5..331aba947 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py @@ -8,7 +8,8 @@ from typing import List, Tuple, Dict, Set, cast -from discopop_explorer.PEGraphX import EdgeType, DepType, PEGraphX, NodeID, CUNode, MemoryRegion +from discopop_explorer.PEGraphX import DepType, PEGraphX, NodeID, CUNode, MemoryRegion +from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, ) diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py index 0fd71f1b0..53897f384 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py @@ -14,13 +14,13 @@ from discopop_explorer.PEGraphX import ( PEGraphX, NodeType, - EdgeType, CUNode, NodeID, MemoryRegion, Dependency, FunctionNode, ) +from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.combined_gpu_patterns.CombinedGPURegions import CombinedGPURegion from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py index 8d29abef6..1e1e6ab0a 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py @@ -8,7 +8,8 @@ from typing import Dict, List, Tuple, Set, Optional -from discopop_explorer.PEGraphX import PEGraphX, EdgeType, NodeID, CUNode, MemoryRegion +from discopop_explorer.PEGraphX import PEGraphX, NodeID, CUNode, MemoryRegion +from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.combined_gpu_patterns.CombinedGPURegions import CombinedGPURegion global_write_unique_id = 0 diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py index 47a4d65a6..beca6911d 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py @@ -15,7 +15,6 @@ from discopop_explorer.PEGraphX import ( PEGraphX, - EdgeType, NodeType, NodeID, MemoryRegion, @@ -23,6 +22,7 @@ Dependency, FunctionNode, ) +from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.combined_gpu_patterns.CombinedGPURegions import CombinedGPURegion from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Enums import UpdateType from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Update import Update diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py index a615454cb..9e49737ef 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py @@ -13,13 +13,13 @@ from discopop_explorer.PEGraphX import ( PEGraphX, - EdgeType, NodeID, MemoryRegion, DepType, CUNode, FunctionNode, ) +from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, ) diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py index eac85d82d..d9ec2cc1f 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py @@ -10,11 +10,11 @@ from discopop_explorer.PEGraphX import ( PEGraphX, - EdgeType, NodeID, FunctionNode, MemoryRegion, ) +from discopop_explorer.enums.EdgeType import EdgeType def get_contained_lines(start_line: str, end_line: str) -> List[str]: diff --git a/discopop_explorer/pattern_detectors/do_all_detector.py b/discopop_explorer/pattern_detectors/do_all_detector.py index 7d7de95ee..3aa01503e 100644 --- a/discopop_explorer/pattern_detectors/do_all_detector.py +++ b/discopop_explorer/pattern_detectors/do_all_detector.py @@ -21,13 +21,13 @@ PEGraphX, Node, NodeType, - EdgeType, LineID, MemoryRegion, DepType, NodeID, Dependency, ) +from ..enums.EdgeType import EdgeType from ..utils import classify_loop_variables, filter_for_hotspots from ..variable import Variable diff --git a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py index d7e0a0988..f72b29e23 100644 --- a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py +++ b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py @@ -15,7 +15,8 @@ from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore from .PatternInfo import PatternInfo -from ..PEGraphX import FunctionNode, LoopNode, NodeID, PEGraphX, Node, EdgeType +from ..PEGraphX import FunctionNode, LoopNode, NodeID, PEGraphX, Node +from ..enums.EdgeType import EdgeType from ..utils import classify_task_vars, filter_for_hotspots, get_child_loops from ..variable import Variable diff --git a/discopop_explorer/pattern_detectors/pipeline_detector.py b/discopop_explorer/pattern_detectors/pipeline_detector.py index f3fc0c88d..cc7b9e10b 100644 --- a/discopop_explorer/pattern_detectors/pipeline_detector.py +++ b/discopop_explorer/pattern_detectors/pipeline_detector.py @@ -20,10 +20,10 @@ NodeID, PEGraphX, Node, - EdgeType, DepType, Dependency, ) +from ..enums.EdgeType import EdgeType from ..utils import correlation_coefficient, classify_task_vars, filter_for_hotspots __pipeline_threshold = 0.9 diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index 9fced17fa..8cab264f7 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -23,11 +23,11 @@ Node, LineID, DepType, - EdgeType, NodeID, MemoryRegion, Dependency, ) +from ..enums.EdgeType import EdgeType from ..utils import filter_for_hotspots, is_reduction_var, classify_loop_variables from ..variable import Variable diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py index 5355c6a27..c78a1f6a2 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py @@ -14,12 +14,12 @@ PEGraphX, CUNode, NodeType, - EdgeType, DepType, NodeID, LoopNode, Node, ) +from ...enums.EdgeType import EdgeType from discopop_explorer.variable import Variable from .GPULoop import GPULoopPattern from .GPUMemory import map_node diff --git a/discopop_explorer/pattern_detectors/task_parallelism/filter.py b/discopop_explorer/pattern_detectors/task_parallelism/filter.py index eb795c54e..8acb6ac32 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/filter.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/filter.py @@ -8,7 +8,8 @@ from typing import List, Dict, cast, Optional, Union -from discopop_explorer.PEGraphX import CUNode, LineID, NodeType, EdgeType, Node, PEGraphX +from discopop_explorer.PEGraphX import CUNode, LineID, NodeType, Node, PEGraphX +from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.task_parallelism.classes import ( TaskParallelismInfo, diff --git a/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py b/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py index c81b8e712..1e2f35ca6 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py @@ -8,7 +8,8 @@ from typing import List, cast, Dict, Optional, Tuple -from discopop_explorer.PEGraphX import Node, EdgeType, PEGraphX +from discopop_explorer.PEGraphX import Node, PEGraphX +from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.task_parallelism.classes import ( TaskParallelismInfo, diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py index 93eed5d31..a671988cd 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py @@ -9,7 +9,8 @@ import copy from typing import List, Tuple, Optional, cast, Dict -from discopop_explorer.PEGraphX import Node, NodeType, EdgeType, PEGraphX +from discopop_explorer.PEGraphX import Node, NodeType, PEGraphX +from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.task_parallelism.classes import ( TaskParallelismInfo, diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py index f25ef84a9..7a69e5119 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py @@ -8,7 +8,8 @@ from typing import List, cast, Tuple, Any -from discopop_explorer.PEGraphX import Node, CUNode, EdgeType, NodeType, PEGraphX, LineID +from discopop_explorer.PEGraphX import Node, CUNode, NodeType, PEGraphX, LineID +from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.task_parallelism.classes import ( ParallelRegionInfo, diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py index 8341948c2..77d8db97a 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py @@ -8,7 +8,8 @@ from typing import List -from discopop_explorer.PEGraphX import EdgeType, FunctionNode, PEGraphX +from discopop_explorer.PEGraphX import FunctionNode, PEGraphX +from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.task_parallelism.classes import ( TaskParallelismInfo, diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py index d03d5065a..8f2ad24dc 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py @@ -11,13 +11,13 @@ from discopop_explorer.PEGraphX import ( CUNode, - EdgeType, FunctionNode, Node, PEGraphX, NodeID, LineID, ) +from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import VarName from discopop_explorer.pattern_detectors.task_parallelism.alias_detection import ( diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py index 05cf01877..ec6c35a6b 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py @@ -13,11 +13,11 @@ FunctionNode, LoopNode, MWType, - EdgeType, Node, PEGraphX, LineID, ) +from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.task_parallelism.classes import ( TaskParallelismInfo, diff --git a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py index adc7cace9..b3f15f2aa 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py @@ -17,12 +17,12 @@ CUNode, Node, NodeType, - EdgeType, MWType, DepType, PEGraphX, LineID, ) +from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.task_parallelism.classes import Task, TaskParallelismInfo from discopop_explorer.utils import depends diff --git a/discopop_explorer/plugins/pipeline.py b/discopop_explorer/plugins/pipeline.py index 1761aa50f..82e7b7f5b 100644 --- a/discopop_explorer/plugins/pipeline.py +++ b/discopop_explorer/plugins/pipeline.py @@ -9,7 +9,8 @@ from copy import deepcopy from typing import List -from ..PEGraphX import LineID, LoopNode, PEGraphX, Node, EdgeType +from ..PEGraphX import LineID, LoopNode, PEGraphX, Node +from ..enums.EdgeType import EdgeType from ..utils import correlation_coefficient total = 0 diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index 35a8542ec..84230cf27 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -24,10 +24,10 @@ NodeType, Node, DepType, - EdgeType, Dependency, MemoryRegion, ) +from .enums.EdgeType import EdgeType from .parser import LoopData from .variable import Variable @@ -832,7 +832,6 @@ def no_inter_iteration_dependency_exists( sub: List[CUNode], root_loop: LoopNode, ) -> bool: - for dep in raw.union(war): if dep[0] in [s.id for s in sub] and dep[1] in [s.id for s in sub]: if dep[2].memory_region in mem_regs: @@ -915,15 +914,7 @@ def classify_task_vars( in_deps: List[Tuple[NodeID, NodeID, Dependency]], out_deps: List[Tuple[NodeID, NodeID, Dependency]], used_in_task_parallelism_detection: bool = False, -) -> Tuple[ - List[Variable], - List[Variable], - List[Variable], - List[Variable], - List[Variable], - List[Variable], - List[str], -]: +) -> Tuple[List[Variable], List[Variable], List[Variable], List[Variable], List[Variable], List[Variable], List[str],]: """Classify task variables :param pet: CU graph diff --git a/discopop_library/discopop_optimizer/DataTransfers/DataTransfers.py b/discopop_library/discopop_optimizer/DataTransfers/DataTransfers.py index 4a942aba8..177bc390e 100644 --- a/discopop_library/discopop_optimizer/DataTransfers/DataTransfers.py +++ b/discopop_library/discopop_optimizer/DataTransfers/DataTransfers.py @@ -8,7 +8,8 @@ from typing import Dict, List, Optional, Set, Tuple, cast import networkx as nx # type: ignore -from discopop_explorer.PEGraphX import EdgeType, MemoryRegion +from discopop_explorer.PEGraphX import MemoryRegion +from discopop_explorer.enums.EdgeType import EdgeType from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel from discopop_library.discopop_optimizer.Variables.Experiment import Experiment diff --git a/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py b/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py index 7d59e5498..c78698758 100644 --- a/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py +++ b/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py @@ -7,7 +7,8 @@ # directory for details. from typing import Tuple, Set, cast -from discopop_explorer.PEGraphX import NodeID, PEGraphX, MemoryRegion, CUNode, EdgeType, DepType +from discopop_explorer.PEGraphX import NodeID, PEGraphX, MemoryRegion, CUNode, DepType +from discopop_explorer.enums.EdgeType import EdgeType from discopop_library.discopop_optimizer.classes.types.DataAccessType import ( WriteDataAccess, ReadDataAccess, diff --git a/discopop_library/discopop_optimizer/PETParser/PETParser.py b/discopop_library/discopop_optimizer/PETParser/PETParser.py index eeff36f62..66428278d 100644 --- a/discopop_library/discopop_optimizer/PETParser/PETParser.py +++ b/discopop_library/discopop_optimizer/PETParser/PETParser.py @@ -19,12 +19,12 @@ from discopop_explorer.PEGraphX import ( PEGraphX, FunctionNode, - EdgeType, LoopNode, CUNode, NodeID, MemoryRegion, ) +from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.utils import calculate_workload from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType from discopop_library.discopop_optimizer.PETParser.DataAccesses.FromCUs import ( diff --git a/discopop_library/discopop_optimizer/classes/nodes/Workload.py b/discopop_library/discopop_optimizer/classes/nodes/Workload.py index 4c133e508..38f02e600 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/Workload.py +++ b/discopop_library/discopop_optimizer/classes/nodes/Workload.py @@ -10,7 +10,8 @@ from sympy import Integer, Expr # type: ignore -from discopop_explorer.PEGraphX import NodeID, PEGraphX, EdgeType +from discopop_explorer.PEGraphX import NodeID, PEGraphX +from discopop_explorer.enums.EdgeType import EdgeType from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel from typing import TYPE_CHECKING diff --git a/discopop_library/discopop_optimizer/optimization/validation.py b/discopop_library/discopop_optimizer/optimization/validation.py index 82c61ca25..de070c159 100644 --- a/discopop_library/discopop_optimizer/optimization/validation.py +++ b/discopop_library/discopop_optimizer/optimization/validation.py @@ -7,7 +7,8 @@ # directory for details. from typing import List, cast, Set -from discopop_explorer.PEGraphX import EdgeType, NodeID +from discopop_explorer.PEGraphX import NodeID +from discopop_explorer.enums.EdgeType import EdgeType from discopop_library.discopop_optimizer.OptimizerArguments import OptimizerArguments from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.nodes.FunctionRoot import FunctionRoot From dffb64c7008d581cdbd27aa4546d416401dd2467 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 30 Jul 2024 16:08:56 +0200 Subject: [PATCH 047/105] refactor: DepType --- discopop_explorer/PEGraphX.py | 8 +------- discopop_explorer/enums/DepType.py | 17 +++++++++++++++++ discopop_explorer/generate_Data_CUInst.py | 2 +- .../combined_gpu_patterns/step_1.py | 3 ++- .../combined_gpu_patterns/step_6.py | 2 +- .../pattern_detectors/do_all_detector.py | 2 +- .../pattern_detectors/pipeline_detector.py | 2 +- .../pattern_detectors/reduction_detector.py | 2 +- .../simple_gpu_patterns/GPULoop.py | 2 +- .../simple_gpu_patterns/GPUMemory.py | 2 +- .../simple_gpu_patterns/GPURegions.py | 2 +- .../task_parallelism/tp_utils.py | 2 +- discopop_explorer/utils.py | 2 +- .../PETParser/DataAccesses/FromCUs.py | 3 ++- 14 files changed, 32 insertions(+), 19 deletions(-) create mode 100644 discopop_explorer/enums/DepType.py diff --git a/discopop_explorer/PEGraphX.py b/discopop_explorer/PEGraphX.py index fb881e3ea..f620cb83b 100644 --- a/discopop_explorer/PEGraphX.py +++ b/discopop_explorer/PEGraphX.py @@ -21,6 +21,7 @@ from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType from discopop_library.HostpotLoader.HotspotType import HotspotType # type:ignore +from .enums.DepType import DepType from .enums.EdgeType import EdgeType from .parser import LoopData, readlineToCUIdMap, writelineToCUIdMap, DependenceItem @@ -56,13 +57,6 @@ def parse_id(node_id: str) -> Tuple[int, int]: return int(split[0]), int(split[1]) -class DepType(Enum): - RAW = 0 - WAR = 1 - WAW = 2 - INIT = 3 - - class NodeType(IntEnum): CU = 0 FUNC = 1 diff --git a/discopop_explorer/enums/DepType.py b/discopop_explorer/enums/DepType.py new file mode 100644 index 000000000..dfa49901a --- /dev/null +++ b/discopop_explorer/enums/DepType.py @@ -0,0 +1,17 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. +from __future__ import annotations + +from enum import Enum + + +class DepType(Enum): + RAW = 0 + WAR = 1 + WAW = 2 + INIT = 3 diff --git a/discopop_explorer/generate_Data_CUInst.py b/discopop_explorer/generate_Data_CUInst.py index 6c9b7bd5b..c4e33f46c 100644 --- a/discopop_explorer/generate_Data_CUInst.py +++ b/discopop_explorer/generate_Data_CUInst.py @@ -17,8 +17,8 @@ NodeID, PEGraphX, Node, - DepType, ) +from .enums.DepType import DepType from .enums.EdgeType import EdgeType from .parser import parse_inputs diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py index 331aba947..d713f1d96 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py @@ -8,7 +8,8 @@ from typing import List, Tuple, Dict, Set, cast -from discopop_explorer.PEGraphX import DepType, PEGraphX, NodeID, CUNode, MemoryRegion +from discopop_explorer.PEGraphX import PEGraphX, NodeID, CUNode, MemoryRegion +from discopop_explorer.enums.DepType import DepType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py index 9e49737ef..9bcf171a5 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py @@ -15,10 +15,10 @@ PEGraphX, NodeID, MemoryRegion, - DepType, CUNode, FunctionNode, ) +from discopop_explorer.enums.DepType import DepType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, diff --git a/discopop_explorer/pattern_detectors/do_all_detector.py b/discopop_explorer/pattern_detectors/do_all_detector.py index 3aa01503e..ca530634a 100644 --- a/discopop_explorer/pattern_detectors/do_all_detector.py +++ b/discopop_explorer/pattern_detectors/do_all_detector.py @@ -23,10 +23,10 @@ NodeType, LineID, MemoryRegion, - DepType, NodeID, Dependency, ) +from ..enums.DepType import DepType from ..enums.EdgeType import EdgeType from ..utils import classify_loop_variables, filter_for_hotspots from ..variable import Variable diff --git a/discopop_explorer/pattern_detectors/pipeline_detector.py b/discopop_explorer/pattern_detectors/pipeline_detector.py index cc7b9e10b..fc200e772 100644 --- a/discopop_explorer/pattern_detectors/pipeline_detector.py +++ b/discopop_explorer/pattern_detectors/pipeline_detector.py @@ -20,9 +20,9 @@ NodeID, PEGraphX, Node, - DepType, Dependency, ) +from ..enums.DepType import DepType from ..enums.EdgeType import EdgeType from ..utils import correlation_coefficient, classify_task_vars, filter_for_hotspots diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index 8cab264f7..d13ca38d7 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -22,11 +22,11 @@ NodeType, Node, LineID, - DepType, NodeID, MemoryRegion, Dependency, ) +from ..enums.DepType import DepType from ..enums.EdgeType import EdgeType from ..utils import filter_for_hotspots, is_reduction_var, classify_loop_variables from ..variable import Variable diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py index 4f28144fa..c193a8fc5 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py @@ -13,7 +13,6 @@ PEGraphX, CUNode, parse_id, - DepType, NodeID, LineID, MemoryRegion, @@ -21,6 +20,7 @@ Node, LoopNode, ) +from ...enums.DepType import DepType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_explorer.utils import ( __get_dep_of_type as get_dep_of_type, diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py index 5bc9a619d..730b22c33 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py @@ -12,7 +12,6 @@ from discopop_explorer.PEGraphX import ( PEGraphX, CUNode, - DepType, NodeID, Node, DummyNode, @@ -20,6 +19,7 @@ LoopNode, Dependency, ) +from discopop_explorer.enums.DepType import DepType from discopop_explorer.utils import is_func_arg, is_global, __get_dep_of_type as get_dep_of_type from discopop_explorer.variable import Variable diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py index c78a1f6a2..fc6f978b1 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py @@ -14,11 +14,11 @@ PEGraphX, CUNode, NodeType, - DepType, NodeID, LoopNode, Node, ) +from ...enums.DepType import DepType from ...enums.EdgeType import EdgeType from discopop_explorer.variable import Variable from .GPULoop import GPULoopPattern diff --git a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py index b3f15f2aa..fb94abb2f 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py @@ -18,10 +18,10 @@ Node, NodeType, MWType, - DepType, PEGraphX, LineID, ) +from discopop_explorer.enums.DepType import DepType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.task_parallelism.classes import Task, TaskParallelismInfo from discopop_explorer.utils import depends diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index 84230cf27..42ca9e9aa 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -23,10 +23,10 @@ PEGraphX, NodeType, Node, - DepType, Dependency, MemoryRegion, ) +from .enums.DepType import DepType from .enums.EdgeType import EdgeType from .parser import LoopData from .variable import Variable diff --git a/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py b/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py index c78698758..8eb6e2b30 100644 --- a/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py +++ b/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py @@ -7,7 +7,8 @@ # directory for details. from typing import Tuple, Set, cast -from discopop_explorer.PEGraphX import NodeID, PEGraphX, MemoryRegion, CUNode, DepType +from discopop_explorer.PEGraphX import NodeID, PEGraphX, MemoryRegion, CUNode +from discopop_explorer.enums.DepType import DepType from discopop_explorer.enums.EdgeType import EdgeType from discopop_library.discopop_optimizer.classes.types.DataAccessType import ( WriteDataAccess, From efa101ba5feb667d8ff571ea089028fef4f15670 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 30 Jul 2024 16:09:45 +0200 Subject: [PATCH 048/105] refactor: MWType --- discopop_explorer/PEGraphX.py | 12 ++---------- discopop_explorer/enums/MWType.py | 19 +++++++++++++++++++ .../task_parallelism/classes.py | 3 ++- .../task_parallelism/suggesters/tasks.py | 2 +- .../task_parallelism_detector.py | 3 ++- .../task_parallelism/tp_utils.py | 2 +- 6 files changed, 27 insertions(+), 14 deletions(-) create mode 100644 discopop_explorer/enums/MWType.py diff --git a/discopop_explorer/PEGraphX.py b/discopop_explorer/PEGraphX.py index f620cb83b..5b628b718 100644 --- a/discopop_explorer/PEGraphX.py +++ b/discopop_explorer/PEGraphX.py @@ -10,7 +10,7 @@ import copy import itertools -from enum import IntEnum, Enum +from enum import IntEnum from typing import Dict, List, Sequence, Tuple, Set, Optional, Type, TypeVar, cast, Union, overload, Any import jsonpickle # type:ignore @@ -23,6 +23,7 @@ from discopop_library.HostpotLoader.HotspotType import HotspotType # type:ignore from .enums.DepType import DepType from .enums.EdgeType import EdgeType +from .enums.MWType import MWType from .parser import LoopData, readlineToCUIdMap, writelineToCUIdMap, DependenceItem from .variable import Variable @@ -64,15 +65,6 @@ class NodeType(IntEnum): DUMMY = 3 -class MWType(Enum): - NONE = 0 - ROOT = 1 - FORK = 2 - WORKER = 3 - BARRIER = 4 - BARRIER_WORKER = 5 - - class NodeID(str): # simpler but still strong typing alternative: # NodeID = NewType("NodeID", str) or remove __init__ diff --git a/discopop_explorer/enums/MWType.py b/discopop_explorer/enums/MWType.py new file mode 100644 index 000000000..1e8b99d23 --- /dev/null +++ b/discopop_explorer/enums/MWType.py @@ -0,0 +1,19 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. +from __future__ import annotations + +from enum import Enum + + +class MWType(Enum): + NONE = 0 + ROOT = 1 + FORK = 2 + WORKER = 3 + BARRIER = 4 + BARRIER_WORKER = 5 diff --git a/discopop_explorer/pattern_detectors/task_parallelism/classes.py b/discopop_explorer/pattern_detectors/task_parallelism/classes.py index 19b64b0b5..0a632872b 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/classes.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/classes.py @@ -9,7 +9,8 @@ from enum import Enum from typing import List, Optional -from discopop_explorer.PEGraphX import LineID, Node, MWType, PEGraphX +from discopop_explorer.PEGraphX import LineID, Node, PEGraphX +from discopop_explorer.enums.MWType import MWType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py index ec6c35a6b..010b7fc78 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py @@ -12,11 +12,11 @@ CUNode, FunctionNode, LoopNode, - MWType, Node, PEGraphX, LineID, ) +from discopop_explorer.enums.MWType import MWType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.task_parallelism.classes import ( diff --git a/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py b/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py index d14699ed4..415f1f47a 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py @@ -9,7 +9,8 @@ from typing import Dict, List, Optional, Tuple, cast -from discopop_explorer.PEGraphX import DummyNode, PEGraphX, MWType +from discopop_explorer.PEGraphX import DummyNode, PEGraphX +from discopop_explorer.enums.MWType import MWType from discopop_explorer.parser import parse_inputs from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.do_all_detector import run_detection as detect_do_all diff --git a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py index fb94abb2f..d83200b4a 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py @@ -17,10 +17,10 @@ CUNode, Node, NodeType, - MWType, PEGraphX, LineID, ) +from discopop_explorer.enums.MWType import MWType from discopop_explorer.enums.DepType import DepType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.task_parallelism.classes import Task, TaskParallelismInfo From 428ee71a50d87c36caa50c8b3a1e155bdea48d7a Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 30 Jul 2024 16:10:33 +0200 Subject: [PATCH 049/105] refactor: NodeType --- discopop_explorer/PEGraphX.py | 9 +-------- discopop_explorer/enums/NodeType.py | 17 +++++++++++++++++ .../combined_gpu_patterns/step_2.py | 2 +- .../combined_gpu_patterns/step_4.py | 2 +- .../pattern_detectors/do_all_detector.py | 2 +- .../pattern_detectors/reduction_detector.py | 2 +- .../simple_gpu_patterns/GPURegions.py | 2 +- .../task_parallelism/filter.py | 3 ++- .../task_parallelism/suggesters/auxiliary.py | 3 ++- .../task_parallelism/suggesters/barriers.py | 3 ++- .../task_parallelism/tp_utils.py | 2 +- discopop_explorer/utils.py | 2 +- 12 files changed, 31 insertions(+), 18 deletions(-) create mode 100644 discopop_explorer/enums/NodeType.py diff --git a/discopop_explorer/PEGraphX.py b/discopop_explorer/PEGraphX.py index 5b628b718..668bbe561 100644 --- a/discopop_explorer/PEGraphX.py +++ b/discopop_explorer/PEGraphX.py @@ -10,7 +10,6 @@ import copy import itertools -from enum import IntEnum from typing import Dict, List, Sequence, Tuple, Set, Optional, Type, TypeVar, cast, Union, overload, Any import jsonpickle # type:ignore @@ -24,6 +23,7 @@ from .enums.DepType import DepType from .enums.EdgeType import EdgeType from .enums.MWType import MWType +from .enums.NodeType import NodeType from .parser import LoopData, readlineToCUIdMap, writelineToCUIdMap, DependenceItem from .variable import Variable @@ -58,13 +58,6 @@ def parse_id(node_id: str) -> Tuple[int, int]: return int(split[0]), int(split[1]) -class NodeType(IntEnum): - CU = 0 - FUNC = 1 - LOOP = 2 - DUMMY = 3 - - class NodeID(str): # simpler but still strong typing alternative: # NodeID = NewType("NodeID", str) or remove __init__ diff --git a/discopop_explorer/enums/NodeType.py b/discopop_explorer/enums/NodeType.py new file mode 100644 index 000000000..a50f7fc45 --- /dev/null +++ b/discopop_explorer/enums/NodeType.py @@ -0,0 +1,17 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. +from __future__ import annotations + +from enum import IntEnum + + +class NodeType(IntEnum): + CU = 0 + FUNC = 1 + LOOP = 2 + DUMMY = 3 diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py index 53897f384..5ca2340b6 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py @@ -13,13 +13,13 @@ from discopop_explorer.PEGraphX import ( PEGraphX, - NodeType, CUNode, NodeID, MemoryRegion, Dependency, FunctionNode, ) +from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.combined_gpu_patterns.CombinedGPURegions import CombinedGPURegion from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py index beca6911d..b992bc699 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py @@ -15,13 +15,13 @@ from discopop_explorer.PEGraphX import ( PEGraphX, - NodeType, NodeID, MemoryRegion, CUNode, Dependency, FunctionNode, ) +from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.combined_gpu_patterns.CombinedGPURegions import CombinedGPURegion from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Enums import UpdateType diff --git a/discopop_explorer/pattern_detectors/do_all_detector.py b/discopop_explorer/pattern_detectors/do_all_detector.py index ca530634a..040c21b66 100644 --- a/discopop_explorer/pattern_detectors/do_all_detector.py +++ b/discopop_explorer/pattern_detectors/do_all_detector.py @@ -20,12 +20,12 @@ LoopNode, PEGraphX, Node, - NodeType, LineID, MemoryRegion, NodeID, Dependency, ) +from ..enums.NodeType import NodeType from ..enums.DepType import DepType from ..enums.EdgeType import EdgeType from ..utils import classify_loop_variables, filter_for_hotspots diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index d13ca38d7..c96957d10 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -19,13 +19,13 @@ CUNode, LoopNode, PEGraphX, - NodeType, Node, LineID, NodeID, MemoryRegion, Dependency, ) +from ..enums.NodeType import NodeType from ..enums.DepType import DepType from ..enums.EdgeType import EdgeType from ..utils import filter_for_hotspots, is_reduction_var, classify_loop_variables diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py index fc6f978b1..9501e061d 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py @@ -13,11 +13,11 @@ from discopop_explorer.PEGraphX import ( PEGraphX, CUNode, - NodeType, NodeID, LoopNode, Node, ) +from ...enums.NodeType import NodeType from ...enums.DepType import DepType from ...enums.EdgeType import EdgeType from discopop_explorer.variable import Variable diff --git a/discopop_explorer/pattern_detectors/task_parallelism/filter.py b/discopop_explorer/pattern_detectors/task_parallelism/filter.py index 8acb6ac32..1a0cf18ea 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/filter.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/filter.py @@ -8,7 +8,8 @@ from typing import List, Dict, cast, Optional, Union -from discopop_explorer.PEGraphX import CUNode, LineID, NodeType, Node, PEGraphX +from discopop_explorer.PEGraphX import CUNode, LineID, Node, PEGraphX +from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.task_parallelism.classes import ( diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py index a671988cd..a8d927e66 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py @@ -9,7 +9,8 @@ import copy from typing import List, Tuple, Optional, cast, Dict -from discopop_explorer.PEGraphX import Node, NodeType, PEGraphX +from discopop_explorer.PEGraphX import Node, PEGraphX +from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.task_parallelism.classes import ( diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py index 7a69e5119..8edb6d03f 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py @@ -8,7 +8,8 @@ from typing import List, cast, Tuple, Any -from discopop_explorer.PEGraphX import Node, CUNode, NodeType, PEGraphX, LineID +from discopop_explorer.PEGraphX import Node, CUNode, PEGraphX, LineID +from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.task_parallelism.classes import ( diff --git a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py index d83200b4a..58f3520f7 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py @@ -16,10 +16,10 @@ FunctionNode, CUNode, Node, - NodeType, PEGraphX, LineID, ) +from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.MWType import MWType from discopop_explorer.enums.DepType import DepType from discopop_explorer.enums.EdgeType import EdgeType diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index 42ca9e9aa..ed7b4ad8e 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -21,11 +21,11 @@ LoopNode, NodeID, PEGraphX, - NodeType, Node, Dependency, MemoryRegion, ) +from .enums.NodeType import NodeType from .enums.DepType import DepType from .enums.EdgeType import EdgeType from .parser import LoopData From f7d1a472c19ad522c8b5aa935a9d585409c98622 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 30 Jul 2024 16:11:48 +0200 Subject: [PATCH 050/105] refactor: NodeID --- discopop_explorer/PEGraphX.py | 18 +------------ discopop_explorer/aliases/NodeID.py | 27 +++++++++++++++++++ discopop_explorer/aliases/__init__.py | 0 discopop_explorer/generate_Data_CUInst.py | 2 +- discopop_explorer/parallel_utils.py | 3 ++- discopop_explorer/pattern_detection.py | 3 ++- .../pattern_detectors/PatternBase.py | 3 ++- .../pattern_detectors/PatternInfo.py | 3 ++- .../CombinedGPURegions.py | 3 ++- .../classes/Dependency.py | 3 ++- .../classes/EntryPoint.py | 3 ++- .../classes/ExitPoint.py | 3 ++- .../combined_gpu_patterns/classes/Update.py | 3 ++- .../combined_gpu_patterns/prepare_metadata.py | 10 +++---- .../combined_gpu_patterns/step_1.py | 3 ++- .../combined_gpu_patterns/step_2.py | 2 +- .../combined_gpu_patterns/step_3.py | 3 ++- .../combined_gpu_patterns/step_4.py | 2 +- .../combined_gpu_patterns/step_5.py | 3 ++- .../combined_gpu_patterns/step_6.py | 2 +- .../combined_gpu_patterns/utilities.py | 2 +- .../pattern_detectors/do_all_detector.py | 2 +- .../geometric_decomposition_detector.py | 3 ++- .../pattern_detectors/pipeline_detector.py | 2 +- .../pattern_detectors/reduction_detector.py | 2 +- .../simple_gpu_patterns/GPULoop.py | 2 +- .../simple_gpu_patterns/GPUMemory.py | 2 +- .../simple_gpu_patterns/GPURegions.py | 2 +- .../simple_gpu_patterns/utils.py | 2 +- .../suggesters/dependency_clauses.py | 2 +- discopop_explorer/utils.py | 2 +- .../PETParser/DataAccesses/FromCUs.py | 3 ++- .../discopop_optimizer/PETParser/PETParser.py | 2 +- .../UpdateOptimization/AddRangesToUpdates.py | 3 ++- .../classes/context/Update.py | 3 ++- .../classes/nodes/DeviceSwitch.py | 2 +- .../classes/nodes/FunctionRoot.py | 2 +- .../classes/nodes/GenericNode.py | 2 +- .../discopop_optimizer/classes/nodes/Loop.py | 2 +- .../classes/nodes/SynchronizationTrigger.py | 2 +- .../classes/nodes/Workload.py | 3 ++- .../evaluate_all_decision_combinations.py | 2 +- .../optimization/evolutionary_algorithm.py | 2 +- .../discopop_optimizer/optimization/greedy.py | 2 +- .../optimization/validation.py | 2 +- .../suggestions/importers/do_all.py | 2 +- .../utilities/MOGUtilities.py | 3 ++- 47 files changed, 94 insertions(+), 65 deletions(-) create mode 100644 discopop_explorer/aliases/NodeID.py create mode 100644 discopop_explorer/aliases/__init__.py diff --git a/discopop_explorer/PEGraphX.py b/discopop_explorer/PEGraphX.py index 668bbe561..860e1124a 100644 --- a/discopop_explorer/PEGraphX.py +++ b/discopop_explorer/PEGraphX.py @@ -20,6 +20,7 @@ from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType from discopop_library.HostpotLoader.HotspotType import HotspotType # type:ignore +from .aliases.NodeID import NodeID from .enums.DepType import DepType from .enums.EdgeType import EdgeType from .enums.MWType import MWType @@ -58,23 +59,6 @@ def parse_id(node_id: str) -> Tuple[int, int]: return int(split[0]), int(split[1]) -class NodeID(str): - # simpler but still strong typing alternative: - # NodeID = NewType("NodeID", str) or remove __init__ - def __init__(self, id_string: str): - # check format of newly created NodeID's - if ":" not in id_string: - raise ValueError("Mal-formatted NodeID: ", id_string) - split_id: List[str] = id_string.split(":") - if len(split_id) != 2: - raise ValueError("Mal-formatted NodeID: ", id_string) - try: - int(split_id[0]) - int(split_id[1]) - except ValueError: - raise ValueError("Mal-formatted NodeID: ", id_string) - - class LineID(str): # simpler but still strong typing alternative: # LineID = NewType("LineID", str) or remove __init__ diff --git a/discopop_explorer/aliases/NodeID.py b/discopop_explorer/aliases/NodeID.py new file mode 100644 index 000000000..f3a9143c6 --- /dev/null +++ b/discopop_explorer/aliases/NodeID.py @@ -0,0 +1,27 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. +from __future__ import annotations + +from typing import List + + +class NodeID(str): + # simpler but still strong typing alternative: + # NodeID = NewType("NodeID", str) or remove __init__ + def __init__(self, id_string: str): + # check format of newly created NodeID's + if ":" not in id_string: + raise ValueError("Mal-formatted NodeID: ", id_string) + split_id: List[str] = id_string.split(":") + if len(split_id) != 2: + raise ValueError("Mal-formatted NodeID: ", id_string) + try: + int(split_id[0]) + int(split_id[1]) + except ValueError: + raise ValueError("Mal-formatted NodeID: ", id_string) diff --git a/discopop_explorer/aliases/__init__.py b/discopop_explorer/aliases/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/discopop_explorer/generate_Data_CUInst.py b/discopop_explorer/generate_Data_CUInst.py index c4e33f46c..6b4edd704 100644 --- a/discopop_explorer/generate_Data_CUInst.py +++ b/discopop_explorer/generate_Data_CUInst.py @@ -14,10 +14,10 @@ FunctionNode, LineID, LoopNode, - NodeID, PEGraphX, Node, ) +from .aliases.NodeID import NodeID from .enums.DepType import DepType from .enums.EdgeType import EdgeType from .parser import parse_inputs diff --git a/discopop_explorer/parallel_utils.py b/discopop_explorer/parallel_utils.py index 818e51b9d..f2ac9cc35 100644 --- a/discopop_explorer/parallel_utils.py +++ b/discopop_explorer/parallel_utils.py @@ -6,7 +6,8 @@ # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. -from .PEGraphX import FunctionNode, Node, NodeID, PEGraphX +from .PEGraphX import FunctionNode, Node, PEGraphX +from .aliases.NodeID import NodeID from typing import Any, List, Optional, Set, Tuple global_pet: Optional[PEGraphX] = None diff --git a/discopop_explorer/pattern_detection.py b/discopop_explorer/pattern_detection.py index 2190baf80..aed7b74ee 100644 --- a/discopop_explorer/pattern_detection.py +++ b/discopop_explorer/pattern_detection.py @@ -28,7 +28,8 @@ ) from discopop_library.discopop_optimizer.utilities.MOGUtilities import get_nodes_from_cu_id from discopop_library.result_classes.DetectionResult import DetectionResult -from .PEGraphX import DummyNode, LoopNode, NodeID, PEGraphX +from .PEGraphX import DummyNode, LoopNode, PEGraphX +from .aliases.NodeID import NodeID from .enums.EdgeType import EdgeType from .pattern_detectors.do_all_detector import DoAllInfo, run_detection as detect_do_all from .pattern_detectors.geometric_decomposition_detector import run_detection as detect_gd diff --git a/discopop_explorer/pattern_detectors/PatternBase.py b/discopop_explorer/pattern_detectors/PatternBase.py index aad4ae694..2acdfd519 100644 --- a/discopop_explorer/pattern_detectors/PatternBase.py +++ b/discopop_explorer/pattern_detectors/PatternBase.py @@ -10,7 +10,8 @@ import os from filelock import FileLock # type: ignore -from discopop_explorer.PEGraphX import LineID, Node, NodeID +from discopop_explorer.PEGraphX import LineID, Node +from discopop_explorer.aliases.NodeID import NodeID class PatternBase(object): diff --git a/discopop_explorer/pattern_detectors/PatternInfo.py b/discopop_explorer/pattern_detectors/PatternInfo.py index cb94dbd67..86700daef 100644 --- a/discopop_explorer/pattern_detectors/PatternInfo.py +++ b/discopop_explorer/pattern_detectors/PatternInfo.py @@ -12,7 +12,8 @@ from discopop_library.discopop_optimizer.classes.system.devices.DeviceTypeEnum import DeviceTypeEnum -from ..PEGraphX import LoopNode, Node, NodeID, LineID, PEGraphX +from ..PEGraphX import LoopNode, Node, LineID, PEGraphX +from ..aliases.NodeID import NodeID from ..utils import calculate_workload, calculate_per_iteration_workload_of_loop diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py index e4281505d..a5ee1fc64 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py @@ -8,7 +8,8 @@ import sys from typing import List, Tuple, Dict, Set, cast -from discopop_explorer.PEGraphX import CUNode, PEGraphX, NodeID, MemoryRegion +from discopop_explorer.PEGraphX import CUNode, PEGraphX, MemoryRegion +from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Dependency.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Dependency.py index 712c66915..23dac4279 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Dependency.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Dependency.py @@ -8,7 +8,8 @@ from typing import Set -from discopop_explorer.PEGraphX import NodeID, MemoryRegion +from discopop_explorer.PEGraphX import MemoryRegion +from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, ) diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py index 18556bcf6..8e3d88012 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py @@ -8,7 +8,8 @@ import os.path from typing import Set, Tuple, List -from discopop_explorer.PEGraphX import PEGraphX, NodeID, MemoryRegion +from discopop_explorer.PEGraphX import PEGraphX, MemoryRegion +from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, ) diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py index ce242cdc7..89b892920 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py @@ -9,7 +9,8 @@ import os from typing import Set, List, Tuple -from discopop_explorer.PEGraphX import PEGraphX, NodeID, MemoryRegion +from discopop_explorer.PEGraphX import PEGraphX, MemoryRegion +from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, ) diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py index 49a6e2581..0a9336438 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py @@ -9,7 +9,8 @@ import os from typing import Set, Dict, cast, Optional, List, Tuple -from discopop_explorer.PEGraphX import LineID, PEGraphX, NodeID, MemoryRegion +from discopop_explorer.PEGraphX import LineID, PEGraphX, MemoryRegion +from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, ) diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/prepare_metadata.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/prepare_metadata.py index 3783bf676..14d11d006 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/prepare_metadata.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/prepare_metadata.py @@ -8,15 +8,15 @@ from typing import Set, List, Tuple -from discopop_explorer.PEGraphX import PEGraphX, NodeID +from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import VarName from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Dependency import Dependency -def get_dependencies_as_metadata(pet: PEGraphX, all_dependencies: Set[Dependency]) -> Tuple[ - List[Tuple[VarName, NodeID, str]], - List[Tuple[VarName, NodeID, str]], -]: +def get_dependencies_as_metadata( + pet: PEGraphX, all_dependencies: Set[Dependency] +) -> Tuple[List[Tuple[VarName, NodeID, str]], List[Tuple[VarName, NodeID, str]],]: in_deps_metadata: Set[Tuple[VarName, NodeID, str]] = set() out_deps_metadata: Set[Tuple[VarName, NodeID, str]] = set() diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py index d713f1d96..c2c3d150b 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py @@ -8,7 +8,8 @@ from typing import List, Tuple, Dict, Set, cast -from discopop_explorer.PEGraphX import PEGraphX, NodeID, CUNode, MemoryRegion +from discopop_explorer.PEGraphX import PEGraphX, CUNode, MemoryRegion +from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.DepType import DepType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py index 5ca2340b6..5654fdd56 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py @@ -14,11 +14,11 @@ from discopop_explorer.PEGraphX import ( PEGraphX, CUNode, - NodeID, MemoryRegion, Dependency, FunctionNode, ) +from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.combined_gpu_patterns.CombinedGPURegions import CombinedGPURegion diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py index 1e1e6ab0a..cb44531c2 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py @@ -8,7 +8,8 @@ from typing import Dict, List, Tuple, Set, Optional -from discopop_explorer.PEGraphX import PEGraphX, NodeID, CUNode, MemoryRegion +from discopop_explorer.PEGraphX import PEGraphX, CUNode, MemoryRegion +from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.combined_gpu_patterns.CombinedGPURegions import CombinedGPURegion diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py index b992bc699..31308d0d3 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py @@ -15,12 +15,12 @@ from discopop_explorer.PEGraphX import ( PEGraphX, - NodeID, MemoryRegion, CUNode, Dependency, FunctionNode, ) +from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.combined_gpu_patterns.CombinedGPURegions import CombinedGPURegion diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_5.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_5.py index 2ea782044..6db78ae83 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_5.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_5.py @@ -8,7 +8,8 @@ from typing import Dict, Set -from discopop_explorer.PEGraphX import PEGraphX, NodeID, MemoryRegion +from discopop_explorer.PEGraphX import PEGraphX, MemoryRegion +from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, ) diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py index 9bcf171a5..e184f0bb3 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py @@ -13,11 +13,11 @@ from discopop_explorer.PEGraphX import ( PEGraphX, - NodeID, MemoryRegion, CUNode, FunctionNode, ) +from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.DepType import DepType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py index d9ec2cc1f..ec8b65213 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py @@ -10,10 +10,10 @@ from discopop_explorer.PEGraphX import ( PEGraphX, - NodeID, FunctionNode, MemoryRegion, ) +from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/do_all_detector.py b/discopop_explorer/pattern_detectors/do_all_detector.py index 040c21b66..4b2e5dafd 100644 --- a/discopop_explorer/pattern_detectors/do_all_detector.py +++ b/discopop_explorer/pattern_detectors/do_all_detector.py @@ -22,9 +22,9 @@ Node, LineID, MemoryRegion, - NodeID, Dependency, ) +from ..aliases.NodeID import NodeID from ..enums.NodeType import NodeType from ..enums.DepType import DepType from ..enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py index f72b29e23..bc7a2a575 100644 --- a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py +++ b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py @@ -15,7 +15,8 @@ from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore from .PatternInfo import PatternInfo -from ..PEGraphX import FunctionNode, LoopNode, NodeID, PEGraphX, Node +from ..PEGraphX import FunctionNode, LoopNode, PEGraphX, Node +from ..aliases.NodeID import NodeID from ..enums.EdgeType import EdgeType from ..utils import classify_task_vars, filter_for_hotspots, get_child_loops from ..variable import Variable diff --git a/discopop_explorer/pattern_detectors/pipeline_detector.py b/discopop_explorer/pattern_detectors/pipeline_detector.py index fc200e772..e16872e43 100644 --- a/discopop_explorer/pattern_detectors/pipeline_detector.py +++ b/discopop_explorer/pattern_detectors/pipeline_detector.py @@ -17,11 +17,11 @@ CUNode, LineID, LoopNode, - NodeID, PEGraphX, Node, Dependency, ) +from ..aliases.NodeID import NodeID from ..enums.DepType import DepType from ..enums.EdgeType import EdgeType from ..utils import correlation_coefficient, classify_task_vars, filter_for_hotspots diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index c96957d10..dbb05e373 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -21,10 +21,10 @@ PEGraphX, Node, LineID, - NodeID, MemoryRegion, Dependency, ) +from ..aliases.NodeID import NodeID from ..enums.NodeType import NodeType from ..enums.DepType import DepType from ..enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py index c193a8fc5..02f8f403a 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py @@ -13,13 +13,13 @@ PEGraphX, CUNode, parse_id, - NodeID, LineID, MemoryRegion, FunctionNode, Node, LoopNode, ) +from ...aliases.NodeID import NodeID from ...enums.DepType import DepType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_explorer.utils import ( diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py index 730b22c33..c39aef0fa 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py @@ -12,13 +12,13 @@ from discopop_explorer.PEGraphX import ( PEGraphX, CUNode, - NodeID, Node, DummyNode, FunctionNode, LoopNode, Dependency, ) +from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.DepType import DepType from discopop_explorer.utils import is_func_arg, is_global, __get_dep_of_type as get_dep_of_type from discopop_explorer.variable import Variable diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py index 9501e061d..684c43267 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py @@ -13,10 +13,10 @@ from discopop_explorer.PEGraphX import ( PEGraphX, CUNode, - NodeID, LoopNode, Node, ) +from ...aliases.NodeID import NodeID from ...enums.NodeType import NodeType from ...enums.DepType import DepType from ...enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/utils.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/utils.py index 168651770..52098dc25 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/utils.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/utils.py @@ -6,7 +6,7 @@ # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. -from discopop_explorer.PEGraphX import NodeID +from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.pattern_detectors.simple_gpu_patterns.GPULoop import GPULoopPattern diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py index 8f2ad24dc..adad79d00 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py @@ -14,9 +14,9 @@ FunctionNode, Node, PEGraphX, - NodeID, LineID, ) +from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import VarName diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index ed7b4ad8e..8afa2c1b9 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -19,12 +19,12 @@ FunctionNode, LineID, LoopNode, - NodeID, PEGraphX, Node, Dependency, MemoryRegion, ) +from .aliases.NodeID import NodeID from .enums.NodeType import NodeType from .enums.DepType import DepType from .enums.EdgeType import EdgeType diff --git a/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py b/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py index 8eb6e2b30..4ea201fbb 100644 --- a/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py +++ b/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py @@ -7,7 +7,8 @@ # directory for details. from typing import Tuple, Set, cast -from discopop_explorer.PEGraphX import NodeID, PEGraphX, MemoryRegion, CUNode +from discopop_explorer.PEGraphX import PEGraphX, MemoryRegion, CUNode +from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.DepType import DepType from discopop_explorer.enums.EdgeType import EdgeType from discopop_library.discopop_optimizer.classes.types.DataAccessType import ( diff --git a/discopop_library/discopop_optimizer/PETParser/PETParser.py b/discopop_library/discopop_optimizer/PETParser/PETParser.py index 66428278d..0b74f2f82 100644 --- a/discopop_library/discopop_optimizer/PETParser/PETParser.py +++ b/discopop_library/discopop_optimizer/PETParser/PETParser.py @@ -21,9 +21,9 @@ FunctionNode, LoopNode, CUNode, - NodeID, MemoryRegion, ) +from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.utils import calculate_workload from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType diff --git a/discopop_library/discopop_optimizer/UpdateOptimization/AddRangesToUpdates.py b/discopop_library/discopop_optimizer/UpdateOptimization/AddRangesToUpdates.py index 8e5cbdecd..62ba7d120 100644 --- a/discopop_library/discopop_optimizer/UpdateOptimization/AddRangesToUpdates.py +++ b/discopop_library/discopop_optimizer/UpdateOptimization/AddRangesToUpdates.py @@ -7,7 +7,8 @@ # directory for details. from typing import Dict, List, Optional, Set, cast -from discopop_explorer.PEGraphX import MemoryRegion, NodeID +from discopop_explorer.PEGraphX import MemoryRegion +from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.variable import Variable from discopop_library.discopop_optimizer.OptimizerArguments import OptimizerArguments from discopop_library.discopop_optimizer.Variables.Experiment import Experiment diff --git a/discopop_library/discopop_optimizer/classes/context/Update.py b/discopop_library/discopop_optimizer/classes/context/Update.py index 779615cdb..fc29090cc 100644 --- a/discopop_library/discopop_optimizer/classes/context/Update.py +++ b/discopop_library/discopop_optimizer/classes/context/Update.py @@ -7,7 +7,8 @@ # directory for details. import json from typing import Any, Dict, Optional, Tuple, cast -from discopop_explorer.PEGraphX import NodeID, PEGraphX +from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.aliases.NodeID import NodeID from discopop_library.discopop_optimizer.classes.types.Aliases import DeviceID from discopop_library.discopop_optimizer.classes.types.DataAccessType import ( ReadDataAccess, diff --git a/discopop_library/discopop_optimizer/classes/nodes/DeviceSwitch.py b/discopop_library/discopop_optimizer/classes/nodes/DeviceSwitch.py index 90d7a5016..b38a8cb6b 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/DeviceSwitch.py +++ b/discopop_library/discopop_optimizer/classes/nodes/DeviceSwitch.py @@ -11,7 +11,7 @@ from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.types.DataAccessType import WriteDataAccess # type: ignore -from discopop_explorer.PEGraphX import NodeID +from discopop_explorer.aliases.NodeID import NodeID from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel from discopop_library.discopop_optimizer.classes.nodes.Workload import Workload from discopop_library.discopop_optimizer.classes.types.DataAccessType import ReadDataAccess diff --git a/discopop_library/discopop_optimizer/classes/nodes/FunctionRoot.py b/discopop_library/discopop_optimizer/classes/nodes/FunctionRoot.py index 25963102f..5d4fbd666 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/FunctionRoot.py +++ b/discopop_library/discopop_optimizer/classes/nodes/FunctionRoot.py @@ -10,7 +10,7 @@ from sympy import Function, Symbol, Integer, Expr # type: ignore -from discopop_explorer.PEGraphX import NodeID +from discopop_explorer.aliases.NodeID import NodeID from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel from typing import TYPE_CHECKING diff --git a/discopop_library/discopop_optimizer/classes/nodes/GenericNode.py b/discopop_library/discopop_optimizer/classes/nodes/GenericNode.py index 5f445e48d..58a134899 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/GenericNode.py +++ b/discopop_library/discopop_optimizer/classes/nodes/GenericNode.py @@ -10,7 +10,7 @@ from sympy import Symbol, Function, Integer # type: ignore -from discopop_explorer.PEGraphX import NodeID +from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel from typing import TYPE_CHECKING diff --git a/discopop_library/discopop_optimizer/classes/nodes/Loop.py b/discopop_library/discopop_optimizer/classes/nodes/Loop.py index 54e40e34a..848eff231 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/Loop.py +++ b/discopop_library/discopop_optimizer/classes/nodes/Loop.py @@ -9,7 +9,7 @@ from sympy import Symbol, Integer, Expr, Float # type: ignore -from discopop_explorer.PEGraphX import NodeID +from discopop_explorer.aliases.NodeID import NodeID from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.nodes.FunctionRoot import FunctionRoot diff --git a/discopop_library/discopop_optimizer/classes/nodes/SynchronizationTrigger.py b/discopop_library/discopop_optimizer/classes/nodes/SynchronizationTrigger.py index 89c62621b..a464a83c5 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/SynchronizationTrigger.py +++ b/discopop_library/discopop_optimizer/classes/nodes/SynchronizationTrigger.py @@ -11,7 +11,7 @@ from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.types.DataAccessType import WriteDataAccess # type: ignore -from discopop_explorer.PEGraphX import NodeID +from discopop_explorer.aliases.NodeID import NodeID from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel from discopop_library.discopop_optimizer.classes.nodes.Workload import Workload from discopop_library.discopop_optimizer.classes.types.DataAccessType import ReadDataAccess diff --git a/discopop_library/discopop_optimizer/classes/nodes/Workload.py b/discopop_library/discopop_optimizer/classes/nodes/Workload.py index 38f02e600..f42e96e4b 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/Workload.py +++ b/discopop_library/discopop_optimizer/classes/nodes/Workload.py @@ -10,7 +10,8 @@ from sympy import Integer, Expr # type: ignore -from discopop_explorer.PEGraphX import NodeID, PEGraphX +from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel from typing import TYPE_CHECKING diff --git a/discopop_library/discopop_optimizer/optimization/evaluate_all_decision_combinations.py b/discopop_library/discopop_optimizer/optimization/evaluate_all_decision_combinations.py index e6f05333e..5edb5b7c2 100644 --- a/discopop_library/discopop_optimizer/optimization/evaluate_all_decision_combinations.py +++ b/discopop_library/discopop_optimizer/optimization/evaluate_all_decision_combinations.py @@ -12,7 +12,7 @@ from sympy import Expr, re import tqdm # type: ignore -from discopop_explorer.PEGraphX import NodeID # type: ignore +from discopop_explorer.aliases.NodeID import NodeID from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel from discopop_library.discopop_optimizer.OptimizerArguments import OptimizerArguments diff --git a/discopop_library/discopop_optimizer/optimization/evolutionary_algorithm.py b/discopop_library/discopop_optimizer/optimization/evolutionary_algorithm.py index 4cb346fe7..d391df437 100644 --- a/discopop_library/discopop_optimizer/optimization/evolutionary_algorithm.py +++ b/discopop_library/discopop_optimizer/optimization/evolutionary_algorithm.py @@ -15,7 +15,7 @@ from sympy import Expr import tqdm # type: ignore -from discopop_explorer.PEGraphX import NodeID # type: ignore +from discopop_explorer.aliases.NodeID import NodeID from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel from discopop_library.discopop_optimizer.OptimizerArguments import OptimizerArguments diff --git a/discopop_library/discopop_optimizer/optimization/greedy.py b/discopop_library/discopop_optimizer/optimization/greedy.py index 52ed6b3f6..1d97d9f82 100644 --- a/discopop_library/discopop_optimizer/optimization/greedy.py +++ b/discopop_library/discopop_optimizer/optimization/greedy.py @@ -14,7 +14,7 @@ from sympy import Expr import tqdm # type: ignore -from discopop_explorer.PEGraphX import NodeID # type: ignore +from discopop_explorer.aliases.NodeID import NodeID from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel from discopop_library.discopop_optimizer.OptimizerArguments import OptimizerArguments diff --git a/discopop_library/discopop_optimizer/optimization/validation.py b/discopop_library/discopop_optimizer/optimization/validation.py index de070c159..66e61f879 100644 --- a/discopop_library/discopop_optimizer/optimization/validation.py +++ b/discopop_library/discopop_optimizer/optimization/validation.py @@ -7,7 +7,7 @@ # directory for details. from typing import List, cast, Set -from discopop_explorer.PEGraphX import NodeID +from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType from discopop_library.discopop_optimizer.OptimizerArguments import OptimizerArguments from discopop_library.discopop_optimizer.Variables.Experiment import Experiment diff --git a/discopop_library/discopop_optimizer/suggestions/importers/do_all.py b/discopop_library/discopop_optimizer/suggestions/importers/do_all.py index c5b95fa26..a510a31cb 100644 --- a/discopop_library/discopop_optimizer/suggestions/importers/do_all.py +++ b/discopop_library/discopop_optimizer/suggestions/importers/do_all.py @@ -11,7 +11,7 @@ import networkx as nx # type: ignore from sympy import Expr, Integer, Symbol, log, Float, init_printing -from discopop_explorer.PEGraphX import NodeID +from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.pattern_detectors.do_all_detector import DoAllInfo # type: ignore from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel diff --git a/discopop_library/discopop_optimizer/utilities/MOGUtilities.py b/discopop_library/discopop_optimizer/utilities/MOGUtilities.py index 3450f6adc..5bf201ad1 100644 --- a/discopop_library/discopop_optimizer/utilities/MOGUtilities.py +++ b/discopop_library/discopop_optimizer/utilities/MOGUtilities.py @@ -16,7 +16,8 @@ import networkx as nx # type: ignore import tqdm # type: ignore -from discopop_explorer.PEGraphX import MemoryRegion, NodeID +from discopop_explorer.PEGraphX import MemoryRegion +from discopop_explorer.aliases.NodeID import NodeID from discopop_library.discopop_optimizer.OptimizerArguments import OptimizerArguments from discopop_library.discopop_optimizer.classes.edges.CallEdge import CallEdge from discopop_library.discopop_optimizer.classes.edges.DataFlowEdge import DataFlowEdge From 052f4c0da9e96fd1e1db6339c81f7e2fb2e55dfa Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 30 Jul 2024 16:12:36 +0200 Subject: [PATCH 051/105] refactor: LineID --- discopop_explorer/PEGraphX.py | 18 +------------ discopop_explorer/aliases/LineID.py | 27 +++++++++++++++++++ discopop_explorer/generate_Data_CUInst.py | 2 +- .../pattern_detectors/PatternBase.py | 3 ++- .../pattern_detectors/PatternInfo.py | 3 ++- .../combined_gpu_patterns/classes/Update.py | 3 ++- .../pattern_detectors/device_updates.py | 2 +- .../pattern_detectors/do_all_detector.py | 2 +- .../pattern_detectors/pipeline_detector.py | 2 +- .../pattern_detectors/reduction_detector.py | 2 +- .../simple_gpu_patterns/GPULoop.py | 2 +- .../gpu_pattern_detector.py | 3 ++- .../task_parallelism/classes.py | 3 ++- .../task_parallelism/filter.py | 3 ++- .../task_parallelism/suggesters/barriers.py | 3 ++- .../suggesters/dependency_clauses.py | 2 +- .../task_parallelism/suggesters/tasks.py | 2 +- .../task_parallelism/tp_utils.py | 2 +- discopop_explorer/plugins/pipeline.py | 3 ++- discopop_explorer/utils.py | 2 +- 20 files changed, 54 insertions(+), 35 deletions(-) create mode 100644 discopop_explorer/aliases/LineID.py diff --git a/discopop_explorer/PEGraphX.py b/discopop_explorer/PEGraphX.py index 860e1124a..aef7f6ae8 100644 --- a/discopop_explorer/PEGraphX.py +++ b/discopop_explorer/PEGraphX.py @@ -20,6 +20,7 @@ from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType from discopop_library.HostpotLoader.HotspotType import HotspotType # type:ignore +from .aliases.LineID import LineID from .aliases.NodeID import NodeID from .enums.DepType import DepType from .enums.EdgeType import EdgeType @@ -59,23 +60,6 @@ def parse_id(node_id: str) -> Tuple[int, int]: return int(split[0]), int(split[1]) -class LineID(str): - # simpler but still strong typing alternative: - # LineID = NewType("LineID", str) or remove __init__ - def __init__(self, id_string: str): - # check format of newly created LineID's - if ":" not in id_string: - raise ValueError("Mal-formatted LineID: ", id_string) - split_id: List[str] = id_string.split(":") - if len(split_id) != 2: - raise ValueError("Mal-formatted LineID: ", id_string) - try: - int(split_id[0]) - int(split_id[1]) - except ValueError: - raise ValueError("Mal-formatted LineID: ", id_string) - - class MemoryRegion(str): # simpler but still strong typing alternative: def __init__(self, id_string: str): diff --git a/discopop_explorer/aliases/LineID.py b/discopop_explorer/aliases/LineID.py new file mode 100644 index 000000000..6a031f313 --- /dev/null +++ b/discopop_explorer/aliases/LineID.py @@ -0,0 +1,27 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. +from __future__ import annotations + +from typing import List + + +class LineID(str): + # simpler but still strong typing alternative: + # LineID = NewType("LineID", str) or remove __init__ + def __init__(self, id_string: str): + # check format of newly created LineID's + if ":" not in id_string: + raise ValueError("Mal-formatted LineID: ", id_string) + split_id: List[str] = id_string.split(":") + if len(split_id) != 2: + raise ValueError("Mal-formatted LineID: ", id_string) + try: + int(split_id[0]) + int(split_id[1]) + except ValueError: + raise ValueError("Mal-formatted LineID: ", id_string) diff --git a/discopop_explorer/generate_Data_CUInst.py b/discopop_explorer/generate_Data_CUInst.py index 6b4edd704..51be06d20 100644 --- a/discopop_explorer/generate_Data_CUInst.py +++ b/discopop_explorer/generate_Data_CUInst.py @@ -12,11 +12,11 @@ from .PEGraphX import ( CUNode, FunctionNode, - LineID, LoopNode, PEGraphX, Node, ) +from .aliases.LineID import LineID from .aliases.NodeID import NodeID from .enums.DepType import DepType from .enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/PatternBase.py b/discopop_explorer/pattern_detectors/PatternBase.py index 2acdfd519..64956fa65 100644 --- a/discopop_explorer/pattern_detectors/PatternBase.py +++ b/discopop_explorer/pattern_detectors/PatternBase.py @@ -10,7 +10,8 @@ import os from filelock import FileLock # type: ignore -from discopop_explorer.PEGraphX import LineID, Node +from discopop_explorer.PEGraphX import Node +from discopop_explorer.aliases.LineID import LineID from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/PatternInfo.py b/discopop_explorer/pattern_detectors/PatternInfo.py index 86700daef..5678b823d 100644 --- a/discopop_explorer/pattern_detectors/PatternInfo.py +++ b/discopop_explorer/pattern_detectors/PatternInfo.py @@ -12,7 +12,8 @@ from discopop_library.discopop_optimizer.classes.system.devices.DeviceTypeEnum import DeviceTypeEnum -from ..PEGraphX import LoopNode, Node, LineID, PEGraphX +from ..PEGraphX import LoopNode, Node, PEGraphX +from ..aliases.LineID import LineID from ..aliases.NodeID import NodeID from ..utils import calculate_workload, calculate_per_iteration_workload_of_loop diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py index 0a9336438..077144676 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py @@ -9,7 +9,8 @@ import os from typing import Set, Dict, cast, Optional, List, Tuple -from discopop_explorer.PEGraphX import LineID, PEGraphX, MemoryRegion +from discopop_explorer.PEGraphX import PEGraphX, MemoryRegion +from discopop_explorer.aliases.LineID import LineID from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, diff --git a/discopop_explorer/pattern_detectors/device_updates.py b/discopop_explorer/pattern_detectors/device_updates.py index b2aa0e42d..b0663b92c 100644 --- a/discopop_explorer/pattern_detectors/device_updates.py +++ b/discopop_explorer/pattern_detectors/device_updates.py @@ -11,9 +11,9 @@ from ..PEGraphX import ( PEGraphX, Node, - LineID, MemoryRegion, ) +from ..aliases.LineID import LineID class DeviceUpdateInfo(PatternInfo): diff --git a/discopop_explorer/pattern_detectors/do_all_detector.py b/discopop_explorer/pattern_detectors/do_all_detector.py index 4b2e5dafd..522ace83d 100644 --- a/discopop_explorer/pattern_detectors/do_all_detector.py +++ b/discopop_explorer/pattern_detectors/do_all_detector.py @@ -20,10 +20,10 @@ LoopNode, PEGraphX, Node, - LineID, MemoryRegion, Dependency, ) +from ..aliases.LineID import LineID from ..aliases.NodeID import NodeID from ..enums.NodeType import NodeType from ..enums.DepType import DepType diff --git a/discopop_explorer/pattern_detectors/pipeline_detector.py b/discopop_explorer/pattern_detectors/pipeline_detector.py index e16872e43..9087c166b 100644 --- a/discopop_explorer/pattern_detectors/pipeline_detector.py +++ b/discopop_explorer/pattern_detectors/pipeline_detector.py @@ -15,12 +15,12 @@ from .PatternInfo import PatternInfo from ..PEGraphX import ( CUNode, - LineID, LoopNode, PEGraphX, Node, Dependency, ) +from ..aliases.LineID import LineID from ..aliases.NodeID import NodeID from ..enums.DepType import DepType from ..enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index dbb05e373..318a09d90 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -20,10 +20,10 @@ LoopNode, PEGraphX, Node, - LineID, MemoryRegion, Dependency, ) +from ..aliases.LineID import LineID from ..aliases.NodeID import NodeID from ..enums.NodeType import NodeType from ..enums.DepType import DepType diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py index 02f8f403a..55d7c3fa7 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py @@ -13,12 +13,12 @@ PEGraphX, CUNode, parse_id, - LineID, MemoryRegion, FunctionNode, Node, LoopNode, ) +from ...aliases.LineID import LineID from ...aliases.NodeID import NodeID from ...enums.DepType import DepType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py index 28edc22ea..1461a49ae 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py @@ -10,7 +10,8 @@ from alive_progress import alive_bar # type: ignore -from discopop_explorer.PEGraphX import LineID, PEGraphX, LoopNode +from discopop_explorer.PEGraphX import PEGraphX, LoopNode +from discopop_explorer.aliases.LineID import LineID from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.simple_gpu_patterns.GPULoop import GPULoopPattern from discopop_explorer.pattern_detectors.simple_gpu_patterns.GPURegions import ( diff --git a/discopop_explorer/pattern_detectors/task_parallelism/classes.py b/discopop_explorer/pattern_detectors/task_parallelism/classes.py index 0a632872b..8319e5ab6 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/classes.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/classes.py @@ -9,7 +9,8 @@ from enum import Enum from typing import List, Optional -from discopop_explorer.PEGraphX import LineID, Node, PEGraphX +from discopop_explorer.PEGraphX import Node, PEGraphX +from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.MWType import MWType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo diff --git a/discopop_explorer/pattern_detectors/task_parallelism/filter.py b/discopop_explorer/pattern_detectors/task_parallelism/filter.py index 1a0cf18ea..837eecedf 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/filter.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/filter.py @@ -8,7 +8,8 @@ from typing import List, Dict, cast, Optional, Union -from discopop_explorer.PEGraphX import CUNode, LineID, Node, PEGraphX +from discopop_explorer.PEGraphX import CUNode, Node, PEGraphX +from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py index 8edb6d03f..6be85a7de 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py @@ -8,7 +8,8 @@ from typing import List, cast, Tuple, Any -from discopop_explorer.PEGraphX import Node, CUNode, PEGraphX, LineID +from discopop_explorer.PEGraphX import Node, CUNode, PEGraphX +from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py index adad79d00..02c8f76aa 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py @@ -14,8 +14,8 @@ FunctionNode, Node, PEGraphX, - LineID, ) +from discopop_explorer.aliases.LineID import LineID from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py index 010b7fc78..f65ba3795 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py @@ -14,8 +14,8 @@ LoopNode, Node, PEGraphX, - LineID, ) +from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.MWType import MWType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo diff --git a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py index 58f3520f7..69637aaef 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py @@ -17,8 +17,8 @@ CUNode, Node, PEGraphX, - LineID, ) +from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.MWType import MWType from discopop_explorer.enums.DepType import DepType diff --git a/discopop_explorer/plugins/pipeline.py b/discopop_explorer/plugins/pipeline.py index 82e7b7f5b..29d11efc1 100644 --- a/discopop_explorer/plugins/pipeline.py +++ b/discopop_explorer/plugins/pipeline.py @@ -9,7 +9,8 @@ from copy import deepcopy from typing import List -from ..PEGraphX import LineID, LoopNode, PEGraphX, Node +from ..PEGraphX import LoopNode, PEGraphX, Node +from ..aliases.LineID import LineID from ..enums.EdgeType import EdgeType from ..utils import correlation_coefficient diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index 8afa2c1b9..4b8cf72c4 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -17,13 +17,13 @@ from .PEGraphX import ( CUNode, FunctionNode, - LineID, LoopNode, PEGraphX, Node, Dependency, MemoryRegion, ) +from .aliases.LineID import LineID from .aliases.NodeID import NodeID from .enums.NodeType import NodeType from .enums.DepType import DepType From c474f4e6a16c0379fb3c9251bfdb61f6321832df Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 30 Jul 2024 16:19:03 +0200 Subject: [PATCH 052/105] refactor: MemoryRegion --- discopop_explorer/PEGraphX.py | 8 +------- discopop_explorer/aliases/MemoryRegion.py | 15 +++++++++++++++ .../combined_gpu_patterns/CombinedGPURegions.py | 3 ++- .../combined_gpu_patterns/classes/Dependency.py | 2 +- .../combined_gpu_patterns/classes/EntryPoint.py | 3 ++- .../combined_gpu_patterns/classes/ExitPoint.py | 3 ++- .../combined_gpu_patterns/classes/Update.py | 3 ++- .../combined_gpu_patterns/step_1.py | 3 ++- .../combined_gpu_patterns/step_2.py | 2 +- .../combined_gpu_patterns/step_3.py | 3 ++- .../combined_gpu_patterns/step_4.py | 2 +- .../combined_gpu_patterns/step_5.py | 3 ++- .../combined_gpu_patterns/step_6.py | 2 +- .../combined_gpu_patterns/utilities.py | 2 +- .../pattern_detectors/device_updates.py | 2 +- .../pattern_detectors/do_all_detector.py | 2 +- .../pattern_detectors/reduction_detector.py | 2 +- .../simple_gpu_patterns/GPULoop.py | 2 +- discopop_explorer/utils.py | 2 +- discopop_library/MemoryRegions/utils.py | 2 +- .../DataTransfers/DataTransfers.py | 2 +- .../DataTransfers/NewDataTransfers.py | 2 +- .../PETParser/DataAccesses/FromCUs.py | 3 ++- .../discopop_optimizer/PETParser/PETParser.py | 2 +- .../UpdateOptimization/AddRangesToUpdates.py | 2 +- .../UpdateOptimization/RemoveLoopIndexUpdates.py | 3 ++- .../discopop_optimizer/Variables/Experiment.py | 2 +- .../classes/context/ContextObject.py | 2 +- .../classes/types/DataAccessType.py | 2 +- .../discopop_optimizer/utilities/MOGUtilities.py | 2 +- 30 files changed, 53 insertions(+), 35 deletions(-) create mode 100644 discopop_explorer/aliases/MemoryRegion.py diff --git a/discopop_explorer/PEGraphX.py b/discopop_explorer/PEGraphX.py index aef7f6ae8..8627ecab5 100644 --- a/discopop_explorer/PEGraphX.py +++ b/discopop_explorer/PEGraphX.py @@ -21,6 +21,7 @@ from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType from discopop_library.HostpotLoader.HotspotType import HotspotType # type:ignore from .aliases.LineID import LineID +from .aliases.MemoryRegion import MemoryRegion from .aliases.NodeID import NodeID from .enums.DepType import DepType from .enums.EdgeType import EdgeType @@ -60,13 +61,6 @@ def parse_id(node_id: str) -> Tuple[int, int]: return int(split[0]), int(split[1]) -class MemoryRegion(str): - # simpler but still strong typing alternative: - def __init__(self, id_string: str): - super().__init__() - pass - - # # check format of newly created MemoryRegion # try: # int(id_string) diff --git a/discopop_explorer/aliases/MemoryRegion.py b/discopop_explorer/aliases/MemoryRegion.py new file mode 100644 index 000000000..7716c1159 --- /dev/null +++ b/discopop_explorer/aliases/MemoryRegion.py @@ -0,0 +1,15 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. +from __future__ import annotations + + +class MemoryRegion(str): + # simpler but still strong typing alternative: + def __init__(self, id_string: str): + super().__init__() + pass diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py index a5ee1fc64..e3276d187 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py @@ -8,7 +8,8 @@ import sys from typing import List, Tuple, Dict, Set, cast -from discopop_explorer.PEGraphX import CUNode, PEGraphX, MemoryRegion +from discopop_explorer.PEGraphX import CUNode, PEGraphX +from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Dependency.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Dependency.py index 23dac4279..b799f3b48 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Dependency.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Dependency.py @@ -8,7 +8,7 @@ from typing import Set -from discopop_explorer.PEGraphX import MemoryRegion +from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py index 8e3d88012..d5373146b 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py @@ -8,7 +8,8 @@ import os.path from typing import Set, Tuple, List -from discopop_explorer.PEGraphX import PEGraphX, MemoryRegion +from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py index 89b892920..bdedf57c4 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py @@ -9,7 +9,8 @@ import os from typing import Set, List, Tuple -from discopop_explorer.PEGraphX import PEGraphX, MemoryRegion +from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py index 077144676..f09673a52 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py @@ -9,7 +9,8 @@ import os from typing import Set, Dict, cast, Optional, List, Tuple -from discopop_explorer.PEGraphX import PEGraphX, MemoryRegion +from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.LineID import LineID from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py index c2c3d150b..c5954d43c 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py @@ -8,7 +8,8 @@ from typing import List, Tuple, Dict, Set, cast -from discopop_explorer.PEGraphX import PEGraphX, CUNode, MemoryRegion +from discopop_explorer.PEGraphX import PEGraphX, CUNode +from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.DepType import DepType from discopop_explorer.enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py index 5654fdd56..9354442c9 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py @@ -14,10 +14,10 @@ from discopop_explorer.PEGraphX import ( PEGraphX, CUNode, - MemoryRegion, Dependency, FunctionNode, ) +from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py index cb44531c2..0fd7e6b56 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py @@ -8,7 +8,8 @@ from typing import Dict, List, Tuple, Set, Optional -from discopop_explorer.PEGraphX import PEGraphX, CUNode, MemoryRegion +from discopop_explorer.PEGraphX import PEGraphX, CUNode +from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.combined_gpu_patterns.CombinedGPURegions import CombinedGPURegion diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py index 31308d0d3..e3afd34aa 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py @@ -15,11 +15,11 @@ from discopop_explorer.PEGraphX import ( PEGraphX, - MemoryRegion, CUNode, Dependency, FunctionNode, ) +from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_5.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_5.py index 6db78ae83..d2409a9bc 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_5.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_5.py @@ -8,7 +8,8 @@ from typing import Dict, Set -from discopop_explorer.PEGraphX import PEGraphX, MemoryRegion +from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py index e184f0bb3..6f6464058 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py @@ -13,10 +13,10 @@ from discopop_explorer.PEGraphX import ( PEGraphX, - MemoryRegion, CUNode, FunctionNode, ) +from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.DepType import DepType from discopop_explorer.enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py index ec8b65213..3bcf105a9 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py @@ -11,8 +11,8 @@ from discopop_explorer.PEGraphX import ( PEGraphX, FunctionNode, - MemoryRegion, ) +from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/device_updates.py b/discopop_explorer/pattern_detectors/device_updates.py index b0663b92c..6205d83b2 100644 --- a/discopop_explorer/pattern_detectors/device_updates.py +++ b/discopop_explorer/pattern_detectors/device_updates.py @@ -11,8 +11,8 @@ from ..PEGraphX import ( PEGraphX, Node, - MemoryRegion, ) +from ..aliases.MemoryRegion import MemoryRegion from ..aliases.LineID import LineID diff --git a/discopop_explorer/pattern_detectors/do_all_detector.py b/discopop_explorer/pattern_detectors/do_all_detector.py index 522ace83d..6b00ab7f1 100644 --- a/discopop_explorer/pattern_detectors/do_all_detector.py +++ b/discopop_explorer/pattern_detectors/do_all_detector.py @@ -20,9 +20,9 @@ LoopNode, PEGraphX, Node, - MemoryRegion, Dependency, ) +from ..aliases.MemoryRegion import MemoryRegion from ..aliases.LineID import LineID from ..aliases.NodeID import NodeID from ..enums.NodeType import NodeType diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index 318a09d90..f6fed4546 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -20,9 +20,9 @@ LoopNode, PEGraphX, Node, - MemoryRegion, Dependency, ) +from ..aliases.MemoryRegion import MemoryRegion from ..aliases.LineID import LineID from ..aliases.NodeID import NodeID from ..enums.NodeType import NodeType diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py index 55d7c3fa7..f667ab846 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py @@ -13,11 +13,11 @@ PEGraphX, CUNode, parse_id, - MemoryRegion, FunctionNode, Node, LoopNode, ) +from ...aliases.MemoryRegion import MemoryRegion from ...aliases.LineID import LineID from ...aliases.NodeID import NodeID from ...enums.DepType import DepType diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index 4b8cf72c4..522885663 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -21,8 +21,8 @@ PEGraphX, Node, Dependency, - MemoryRegion, ) +from .aliases.MemoryRegion import MemoryRegion from .aliases.LineID import LineID from .aliases.NodeID import NodeID from .enums.NodeType import NodeType diff --git a/discopop_library/MemoryRegions/utils.py b/discopop_library/MemoryRegions/utils.py index e2f0eb56b..6b83e2df2 100644 --- a/discopop_library/MemoryRegions/utils.py +++ b/discopop_library/MemoryRegions/utils.py @@ -10,7 +10,7 @@ import os.path from typing import Dict, Set, cast -from discopop_explorer.PEGraphX import MemoryRegion +from discopop_explorer.aliases.MemoryRegion import MemoryRegion def get_sizes_of_memory_regions( diff --git a/discopop_library/discopop_optimizer/DataTransfers/DataTransfers.py b/discopop_library/discopop_optimizer/DataTransfers/DataTransfers.py index 177bc390e..b2bd59a58 100644 --- a/discopop_library/discopop_optimizer/DataTransfers/DataTransfers.py +++ b/discopop_library/discopop_optimizer/DataTransfers/DataTransfers.py @@ -8,7 +8,7 @@ from typing import Dict, List, Optional, Set, Tuple, cast import networkx as nx # type: ignore -from discopop_explorer.PEGraphX import MemoryRegion +from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.enums.EdgeType import EdgeType from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel diff --git a/discopop_library/discopop_optimizer/DataTransfers/NewDataTransfers.py b/discopop_library/discopop_optimizer/DataTransfers/NewDataTransfers.py index b56e70542..2e35b2a7c 100644 --- a/discopop_library/discopop_optimizer/DataTransfers/NewDataTransfers.py +++ b/discopop_library/discopop_optimizer/DataTransfers/NewDataTransfers.py @@ -9,7 +9,7 @@ import logging from typing import Dict, List, Optional, Set, Tuple, cast import networkx as nx # type: ignore -from discopop_explorer.PEGraphX import MemoryRegion +from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel from discopop_library.discopop_optimizer.OptimizerArguments import OptimizerArguments diff --git a/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py b/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py index 4ea201fbb..94939717a 100644 --- a/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py +++ b/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py @@ -7,7 +7,8 @@ # directory for details. from typing import Tuple, Set, cast -from discopop_explorer.PEGraphX import PEGraphX, MemoryRegion, CUNode +from discopop_explorer.PEGraphX import PEGraphX, CUNode +from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.DepType import DepType from discopop_explorer.enums.EdgeType import EdgeType diff --git a/discopop_library/discopop_optimizer/PETParser/PETParser.py b/discopop_library/discopop_optimizer/PETParser/PETParser.py index 0b74f2f82..134232b40 100644 --- a/discopop_library/discopop_optimizer/PETParser/PETParser.py +++ b/discopop_library/discopop_optimizer/PETParser/PETParser.py @@ -21,8 +21,8 @@ FunctionNode, LoopNode, CUNode, - MemoryRegion, ) +from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.utils import calculate_workload diff --git a/discopop_library/discopop_optimizer/UpdateOptimization/AddRangesToUpdates.py b/discopop_library/discopop_optimizer/UpdateOptimization/AddRangesToUpdates.py index 62ba7d120..457e9011a 100644 --- a/discopop_library/discopop_optimizer/UpdateOptimization/AddRangesToUpdates.py +++ b/discopop_library/discopop_optimizer/UpdateOptimization/AddRangesToUpdates.py @@ -7,7 +7,7 @@ # directory for details. from typing import Dict, List, Optional, Set, cast -from discopop_explorer.PEGraphX import MemoryRegion +from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.variable import Variable from discopop_library.discopop_optimizer.OptimizerArguments import OptimizerArguments diff --git a/discopop_library/discopop_optimizer/UpdateOptimization/RemoveLoopIndexUpdates.py b/discopop_library/discopop_optimizer/UpdateOptimization/RemoveLoopIndexUpdates.py index 872194084..0065156ec 100644 --- a/discopop_library/discopop_optimizer/UpdateOptimization/RemoveLoopIndexUpdates.py +++ b/discopop_library/discopop_optimizer/UpdateOptimization/RemoveLoopIndexUpdates.py @@ -8,7 +8,8 @@ import logging from typing import List, Set, cast -from discopop_explorer.PEGraphX import LoopNode, MemoryRegion +from discopop_explorer.PEGraphX import LoopNode +from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_library.discopop_optimizer.OptimizerArguments import OptimizerArguments from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.context.Update import Update diff --git a/discopop_library/discopop_optimizer/Variables/Experiment.py b/discopop_library/discopop_optimizer/Variables/Experiment.py index 8381e9be9..2c28077ba 100644 --- a/discopop_library/discopop_optimizer/Variables/Experiment.py +++ b/discopop_library/discopop_optimizer/Variables/Experiment.py @@ -13,7 +13,7 @@ import networkx as nx # type: ignore from sympy import Integer, Symbol, Expr, Float # type: ignore -from discopop_explorer.PEGraphX import MemoryRegion +from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_library.HostpotLoader.HotspotType import HotspotType from discopop_library.MemoryRegions.utils import get_sizes_of_memory_regions from discopop_library.PathManagement.PathManagement import load_file_mapping diff --git a/discopop_library/discopop_optimizer/classes/context/ContextObject.py b/discopop_library/discopop_optimizer/classes/context/ContextObject.py index c989a91ea..a55399c7e 100644 --- a/discopop_library/discopop_optimizer/classes/context/ContextObject.py +++ b/discopop_library/discopop_optimizer/classes/context/ContextObject.py @@ -13,7 +13,7 @@ from sympy import Expr, Integer, Symbol # type: ignore import networkx as nx # type: ignore -from discopop_explorer.PEGraphX import MemoryRegion +from discopop_explorer.aliases.MemoryRegion import MemoryRegion from typing import TYPE_CHECKING if TYPE_CHECKING: diff --git a/discopop_library/discopop_optimizer/classes/types/DataAccessType.py b/discopop_library/discopop_optimizer/classes/types/DataAccessType.py index f9b3b8b02..74d05336f 100644 --- a/discopop_library/discopop_optimizer/classes/types/DataAccessType.py +++ b/discopop_library/discopop_optimizer/classes/types/DataAccessType.py @@ -7,7 +7,7 @@ # directory for details. from typing import Any, Dict, Optional -from discopop_explorer.PEGraphX import MemoryRegion +from discopop_explorer.aliases.MemoryRegion import MemoryRegion class ReadDataAccess(object): diff --git a/discopop_library/discopop_optimizer/utilities/MOGUtilities.py b/discopop_library/discopop_optimizer/utilities/MOGUtilities.py index 5bf201ad1..21d47c282 100644 --- a/discopop_library/discopop_optimizer/utilities/MOGUtilities.py +++ b/discopop_library/discopop_optimizer/utilities/MOGUtilities.py @@ -16,7 +16,7 @@ import networkx as nx # type: ignore import tqdm # type: ignore -from discopop_explorer.PEGraphX import MemoryRegion +from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_library.discopop_optimizer.OptimizerArguments import OptimizerArguments from discopop_library.discopop_optimizer.classes.edges.CallEdge import CallEdge From 8be9d1fb399923f9aa1fa2820b0a50aeff330aba Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 30 Jul 2024 16:21:59 +0200 Subject: [PATCH 053/105] refactor: Dependency --- discopop_explorer/PEGraphX.py | 30 +------------ discopop_explorer/classes/Dependency.py | 45 +++++++++++++++++++ discopop_explorer/classes/__init__.py | 0 .../combined_gpu_patterns/step_2.py | 2 +- .../combined_gpu_patterns/step_4.py | 2 +- .../pattern_detectors/do_all_detector.py | 2 +- .../pattern_detectors/pipeline_detector.py | 2 +- .../pattern_detectors/reduction_detector.py | 2 +- .../simple_gpu_patterns/GPUMemory.py | 2 +- discopop_explorer/utils.py | 2 +- 10 files changed, 53 insertions(+), 36 deletions(-) create mode 100644 discopop_explorer/classes/Dependency.py create mode 100644 discopop_explorer/classes/__init__.py diff --git a/discopop_explorer/PEGraphX.py b/discopop_explorer/PEGraphX.py index 8627ecab5..89e651cae 100644 --- a/discopop_explorer/PEGraphX.py +++ b/discopop_explorer/PEGraphX.py @@ -23,6 +23,7 @@ from .aliases.LineID import LineID from .aliases.MemoryRegion import MemoryRegion from .aliases.NodeID import NodeID +from .classes.Dependency import Dependency from .enums.DepType import DepType from .enums.EdgeType import EdgeType from .enums.MWType import MWType @@ -68,35 +69,6 @@ def parse_id(node_id: str) -> Tuple[int, int]: # raise ValueError("Mal-formatted MemoryRegion identifier: ", id_string) -class Dependency: - etype: EdgeType - dtype: Optional[DepType] = None - var_name: Optional[str] = None - memory_region: Optional[MemoryRegion] = None - source_line: Optional[LineID] = None - sink_line: Optional[LineID] = None - intra_iteration: bool = False - intra_iteration_level: int = -1 - metadata_intra_iteration_dep: List[LineID] - metadata_inter_iteration_dep: List[LineID] - metadata_intra_call_dep: List[LineID] - metadata_inter_call_dep: List[LineID] - metadata_sink_ancestors: List[LineID] - metadata_source_ancestors: List[LineID] - - def __init__(self, type: EdgeType): - self.etype = type - self.metadata_intra_iteration_dep = [] - self.metadata_inter_iteration_dep = [] - self.metadata_intra_call_dep = [] - self.metadata_inter_call_dep = [] - self.metadata_sink_ancestors = [] - self.metadata_source_ancestors = [] - - def __str__(self) -> str: - return self.var_name if self.var_name is not None else str(self.etype) - - # TODO make the Node class abstract class Node: # properties of every Node diff --git a/discopop_explorer/classes/Dependency.py b/discopop_explorer/classes/Dependency.py new file mode 100644 index 000000000..e9e7429ab --- /dev/null +++ b/discopop_explorer/classes/Dependency.py @@ -0,0 +1,45 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from __future__ import annotations + +from typing import Optional, List + +from discopop_explorer.aliases.LineID import LineID +from discopop_explorer.aliases.MemoryRegion import MemoryRegion +from discopop_explorer.enums.DepType import DepType +from discopop_explorer.enums.EdgeType import EdgeType + + +class Dependency: + etype: EdgeType + dtype: Optional[DepType] = None + var_name: Optional[str] = None + memory_region: Optional[MemoryRegion] = None + source_line: Optional[LineID] = None + sink_line: Optional[LineID] = None + intra_iteration: bool = False + intra_iteration_level: int = -1 + metadata_intra_iteration_dep: List[LineID] + metadata_inter_iteration_dep: List[LineID] + metadata_intra_call_dep: List[LineID] + metadata_inter_call_dep: List[LineID] + metadata_sink_ancestors: List[LineID] + metadata_source_ancestors: List[LineID] + + def __init__(self, type: EdgeType): + self.etype = type + self.metadata_intra_iteration_dep = [] + self.metadata_inter_iteration_dep = [] + self.metadata_intra_call_dep = [] + self.metadata_inter_call_dep = [] + self.metadata_sink_ancestors = [] + self.metadata_source_ancestors = [] + + def __str__(self) -> str: + return self.var_name if self.var_name is not None else str(self.etype) diff --git a/discopop_explorer/classes/__init__.py b/discopop_explorer/classes/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py index 9354442c9..c12f24d91 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py @@ -14,9 +14,9 @@ from discopop_explorer.PEGraphX import ( PEGraphX, CUNode, - Dependency, FunctionNode, ) +from discopop_explorer.classes.Dependency import Dependency from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.NodeType import NodeType diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py index e3afd34aa..0b9ad4cfb 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py @@ -16,9 +16,9 @@ from discopop_explorer.PEGraphX import ( PEGraphX, CUNode, - Dependency, FunctionNode, ) +from discopop_explorer.classes.Dependency import Dependency from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.NodeType import NodeType diff --git a/discopop_explorer/pattern_detectors/do_all_detector.py b/discopop_explorer/pattern_detectors/do_all_detector.py index 6b00ab7f1..f7768dfb9 100644 --- a/discopop_explorer/pattern_detectors/do_all_detector.py +++ b/discopop_explorer/pattern_detectors/do_all_detector.py @@ -20,8 +20,8 @@ LoopNode, PEGraphX, Node, - Dependency, ) +from ..classes.Dependency import Dependency from ..aliases.MemoryRegion import MemoryRegion from ..aliases.LineID import LineID from ..aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/pipeline_detector.py b/discopop_explorer/pattern_detectors/pipeline_detector.py index 9087c166b..bd4fadd72 100644 --- a/discopop_explorer/pattern_detectors/pipeline_detector.py +++ b/discopop_explorer/pattern_detectors/pipeline_detector.py @@ -18,8 +18,8 @@ LoopNode, PEGraphX, Node, - Dependency, ) +from ..classes.Dependency import Dependency from ..aliases.LineID import LineID from ..aliases.NodeID import NodeID from ..enums.DepType import DepType diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index f6fed4546..e5d401fd5 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -20,8 +20,8 @@ LoopNode, PEGraphX, Node, - Dependency, ) +from ..classes.Dependency import Dependency from ..aliases.MemoryRegion import MemoryRegion from ..aliases.LineID import LineID from ..aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py index c39aef0fa..ec880126b 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py @@ -16,8 +16,8 @@ DummyNode, FunctionNode, LoopNode, - Dependency, ) +from discopop_explorer.classes.Dependency import Dependency from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.DepType import DepType from discopop_explorer.utils import is_func_arg, is_global, __get_dep_of_type as get_dep_of_type diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index 522885663..bf64a902d 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -20,8 +20,8 @@ LoopNode, PEGraphX, Node, - Dependency, ) +from .classes.Dependency import Dependency from .aliases.MemoryRegion import MemoryRegion from .aliases.LineID import LineID from .aliases.NodeID import NodeID From 551253423001ea7567b026468a90bbc526926276 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 30 Jul 2024 16:31:51 +0200 Subject: [PATCH 054/105] fix: updated .gitignore --- .gitignore | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 2f6d661c3..f8c226bf9 100644 --- a/.gitignore +++ b/.gitignore @@ -71,6 +71,10 @@ coverage.xml # Profiling reports profiling_stats.txt +# Code structure diagrams +classes.png +packages.png + # Translations *.mo *.pot @@ -163,4 +167,4 @@ _deps !/test/**/Makefile **/.discopop -**/prog \ No newline at end of file +**/prog From a3d34709b5f0d412caa33dbb7846764119d9aef1 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 30 Jul 2024 16:48:00 +0200 Subject: [PATCH 055/105] refactor: Node --- discopop_explorer/PEGraphX.py | 99 +-------------- discopop_explorer/classes/Node.py | 114 ++++++++++++++++++ discopop_explorer/generate_Data_CUInst.py | 2 +- discopop_explorer/json_serializer.py | 2 +- discopop_explorer/parallel_utils.py | 3 +- discopop_explorer/parser.py | 2 + .../pattern_detectors/PatternBase.py | 2 +- .../pattern_detectors/PatternInfo.py | 3 +- .../pattern_detectors/device_updates.py | 2 +- .../pattern_detectors/do_all_detector.py | 2 +- .../geometric_decomposition_detector.py | 3 +- .../pattern_detectors/pipeline_detector.py | 2 +- .../pattern_detectors/reduction_detector.py | 2 +- .../simple_gpu_patterns/GPULoop.py | 2 +- .../simple_gpu_patterns/GPUMemory.py | 2 +- .../simple_gpu_patterns/GPURegions.py | 2 +- .../task_parallelism/alias_detection.py | 2 + .../task_parallelism/classes.py | 3 +- .../task_parallelism/filter.py | 3 +- .../task_parallelism/postprocessor.py | 3 +- .../task_parallelism/preprocessor.py | 1 + .../task_parallelism/suggesters/auxiliary.py | 3 +- .../task_parallelism/suggesters/barriers.py | 3 +- .../suggesters/dependency_clauses.py | 2 +- .../task_parallelism/suggesters/tasks.py | 2 +- .../task_parallelism/tp_utils.py | 3 +- discopop_explorer/plugins/pipeline.py | 3 +- discopop_explorer/utils.py | 2 +- .../result_classes/MergedPattern.py | 2 +- .../result_classes/OptimizerOutputPattern.py | 2 +- 30 files changed, 155 insertions(+), 123 deletions(-) create mode 100644 discopop_explorer/classes/Node.py diff --git a/discopop_explorer/PEGraphX.py b/discopop_explorer/PEGraphX.py index 89e651cae..5e442417f 100644 --- a/discopop_explorer/PEGraphX.py +++ b/discopop_explorer/PEGraphX.py @@ -24,9 +24,9 @@ from .aliases.MemoryRegion import MemoryRegion from .aliases.NodeID import NodeID from .classes.Dependency import Dependency +from .classes.Node import Node from .enums.DepType import DepType from .enums.EdgeType import EdgeType -from .enums.MWType import MWType from .enums.NodeType import NodeType from .parser import LoopData, readlineToCUIdMap, writelineToCUIdMap, DependenceItem @@ -69,103 +69,6 @@ def parse_id(node_id: str) -> Tuple[int, int]: # raise ValueError("Mal-formatted MemoryRegion identifier: ", id_string) -# TODO make the Node class abstract -class Node: - # properties of every Node - id: NodeID - file_id: int - node_id: int - start_line: int - end_line: int - type: NodeType - name: str - parent_function_id: Optional[ - NodeID - ] = None # metadata to speedup some calculations (TODO FunctionNodes have themselves as parent) - workload: Optional[int] = None - - # properties of CU Nodes - node_calls: List[Dict[str, str]] = [] - recursive_function_calls: List[str] = [] - - # properties related to pattern analysis - reduction: bool = False - do_all: bool = False - geometric_decomposition: bool = False - pipeline: float = -1 - tp_contains_task: bool = False - tp_contains_taskwait: bool = False - tp_omittable: bool = False - mw_type = MWType.FORK - - def __init__(self, node_id: NodeID): - self.id = node_id - self.file_id, self.node_id = parse_id(node_id) - - # @classmethod - # def from_kwargs(cls, node_id: NodeID, **kwargs) -> Node: - # node = cls(node_id) - # for key, value in kwargs.items(): - # setattr(node, key, value) - # return node - - def start_position(self) -> LineID: - """Start position file_id:line - e.g. 23:45 - - :return: - """ - - return LineID(f"{self.file_id}:{self.start_line}") - - def end_position(self) -> LineID: - """End position file_id:line - e.g. 23:45 - - :return: - """ - return LineID(f"{self.file_id}:{self.end_line}") - - def contains_line(self, other_line: str) -> bool: - if other_line == "GlobalVar" or other_line == "LineNotFound": - return False - if not ":" in other_line: - return False - other_file_id = int(other_line.split(":")[0]) - other_line_num = int(other_line.split(":")[1]) - if other_file_id != self.file_id: - return False - if other_line_num >= self.start_line and other_line_num <= self.end_line: - return True - return False - - def __str__(self) -> str: - return self.id - - def __eq__(self, other: Any) -> bool: - return isinstance(other, Node) and other.file_id == self.file_id and other.node_id == self.node_id - - def __hash__(self) -> int: - return hash(self.id) - - def get_parent_id(self, pet: PEGraphX) -> Optional[NodeID]: - parents = [s for s, t, d in pet.in_edges(self.id, EdgeType.CHILD)] - if len(parents) == 0: - return None - elif len(parents) == 1: - return parents[0] - else: - # it is possible that a node has a function-type and e.g. loop type parent - # in this case, return the non-function type parent, since it will be a child of the function itself. - if len(parents) > 2: - raise ValueError("Node: ", self.id, "has too many parents!") - else: - for parent in parents: - if type(pet.node_at(parent)) != FunctionNode: - return parent - return None - - # Data.xml: type="0" class CUNode(Node): instructions_count: int = -1 diff --git a/discopop_explorer/classes/Node.py b/discopop_explorer/classes/Node.py new file mode 100644 index 000000000..d8ab0baaf --- /dev/null +++ b/discopop_explorer/classes/Node.py @@ -0,0 +1,114 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. +from __future__ import annotations + +from typing import Optional, List, Dict, Any + +from discopop_explorer.PEGraphX import parse_id, PEGraphX, FunctionNode +from discopop_explorer.aliases.LineID import LineID +from discopop_explorer.aliases.NodeID import NodeID +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.enums.MWType import MWType +from discopop_explorer.enums.NodeType import NodeType + + +# TODO make the Node class abstract +class Node: + # properties of every Node + id: NodeID + file_id: int + node_id: int + start_line: int + end_line: int + type: NodeType + name: str + parent_function_id: Optional[ + NodeID + ] = None # metadata to speedup some calculations (TODO FunctionNodes have themselves as parent) + workload: Optional[int] = None + + # properties of CU Nodes + node_calls: List[Dict[str, str]] = [] + recursive_function_calls: List[str] = [] + + # properties related to pattern analysis + reduction: bool = False + do_all: bool = False + geometric_decomposition: bool = False + pipeline: float = -1 + tp_contains_task: bool = False + tp_contains_taskwait: bool = False + tp_omittable: bool = False + mw_type = MWType.FORK + + def __init__(self, node_id: NodeID): + self.id = node_id + self.file_id, self.node_id = parse_id(node_id) + + # @classmethod + # def from_kwargs(cls, node_id: NodeID, **kwargs) -> Node: + # node = cls(node_id) + # for key, value in kwargs.items(): + # setattr(node, key, value) + # return node + + def start_position(self) -> LineID: + """Start position file_id:line + e.g. 23:45 + + :return: + """ + + return LineID(f"{self.file_id}:{self.start_line}") + + def end_position(self) -> LineID: + """End position file_id:line + e.g. 23:45 + + :return: + """ + return LineID(f"{self.file_id}:{self.end_line}") + + def contains_line(self, other_line: str) -> bool: + if other_line == "GlobalVar" or other_line == "LineNotFound": + return False + if not ":" in other_line: + return False + other_file_id = int(other_line.split(":")[0]) + other_line_num = int(other_line.split(":")[1]) + if other_file_id != self.file_id: + return False + if other_line_num >= self.start_line and other_line_num <= self.end_line: + return True + return False + + def __str__(self) -> str: + return self.id + + def __eq__(self, other: Any) -> bool: + return isinstance(other, Node) and other.file_id == self.file_id and other.node_id == self.node_id + + def __hash__(self) -> int: + return hash(self.id) + + def get_parent_id(self, pet: PEGraphX) -> Optional[NodeID]: + parents = [s for s, t, d in pet.in_edges(self.id, EdgeType.CHILD)] + if len(parents) == 0: + return None + elif len(parents) == 1: + return parents[0] + else: + # it is possible that a node has a function-type and e.g. loop type parent + # in this case, return the non-function type parent, since it will be a child of the function itself. + if len(parents) > 2: + raise ValueError("Node: ", self.id, "has too many parents!") + else: + for parent in parents: + if type(pet.node_at(parent)) != FunctionNode: + return parent + return None diff --git a/discopop_explorer/generate_Data_CUInst.py b/discopop_explorer/generate_Data_CUInst.py index 51be06d20..8dd5c39e2 100644 --- a/discopop_explorer/generate_Data_CUInst.py +++ b/discopop_explorer/generate_Data_CUInst.py @@ -14,8 +14,8 @@ FunctionNode, LoopNode, PEGraphX, - Node, ) +from .classes.Node import Node from .aliases.LineID import LineID from .aliases.NodeID import NodeID from .enums.DepType import DepType diff --git a/discopop_explorer/json_serializer.py b/discopop_explorer/json_serializer.py index 1281f36f0..56d7a10ae 100644 --- a/discopop_explorer/json_serializer.py +++ b/discopop_explorer/json_serializer.py @@ -14,7 +14,7 @@ from discopop_library.result_classes.DetectionResult import DetectionResult from discopop_library.result_classes.PatternStorage import PatternStorage -from .PEGraphX import Node +from .classes.Node import Node from .pattern_detectors.PatternInfo import PatternInfo from .pattern_detectors.pipeline_detector import PipelineStage from .pattern_detectors.task_parallelism.classes import TPIType diff --git a/discopop_explorer/parallel_utils.py b/discopop_explorer/parallel_utils.py index f2ac9cc35..cb8b02658 100644 --- a/discopop_explorer/parallel_utils.py +++ b/discopop_explorer/parallel_utils.py @@ -6,7 +6,8 @@ # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. -from .PEGraphX import FunctionNode, Node, PEGraphX +from .PEGraphX import FunctionNode, PEGraphX +from .classes.Node import Node from .aliases.NodeID import NodeID from typing import Any, List, Optional, Set, Tuple diff --git a/discopop_explorer/parser.py b/discopop_explorer/parser.py index 9b8b4ff26..89abc5d59 100644 --- a/discopop_explorer/parser.py +++ b/discopop_explorer/parser.py @@ -18,6 +18,8 @@ from lxml import objectify # type:ignore from lxml.objectify import ObjectifiedElement # type: ignore +import discopop_explorer.classes.Node + # Map to record which line belongs to read set of nodes. LID -> NodeIds readlineToCUIdMap = defaultdict(set) # type: ignore # Map to record which line belongs to write set of nodes. LID -> NodeIds diff --git a/discopop_explorer/pattern_detectors/PatternBase.py b/discopop_explorer/pattern_detectors/PatternBase.py index 64956fa65..ae0173ea9 100644 --- a/discopop_explorer/pattern_detectors/PatternBase.py +++ b/discopop_explorer/pattern_detectors/PatternBase.py @@ -10,7 +10,7 @@ import os from filelock import FileLock # type: ignore -from discopop_explorer.PEGraphX import Node +from discopop_explorer.classes.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/PatternInfo.py b/discopop_explorer/pattern_detectors/PatternInfo.py index 5678b823d..7364b27e1 100644 --- a/discopop_explorer/pattern_detectors/PatternInfo.py +++ b/discopop_explorer/pattern_detectors/PatternInfo.py @@ -12,7 +12,8 @@ from discopop_library.discopop_optimizer.classes.system.devices.DeviceTypeEnum import DeviceTypeEnum -from ..PEGraphX import LoopNode, Node, PEGraphX +from ..PEGraphX import LoopNode, PEGraphX +from ..classes.Node import Node from ..aliases.LineID import LineID from ..aliases.NodeID import NodeID from ..utils import calculate_workload, calculate_per_iteration_workload_of_loop diff --git a/discopop_explorer/pattern_detectors/device_updates.py b/discopop_explorer/pattern_detectors/device_updates.py index 6205d83b2..4ec55c791 100644 --- a/discopop_explorer/pattern_detectors/device_updates.py +++ b/discopop_explorer/pattern_detectors/device_updates.py @@ -10,8 +10,8 @@ from .PatternInfo import PatternInfo from ..PEGraphX import ( PEGraphX, - Node, ) +from ..classes.Node import Node from ..aliases.MemoryRegion import MemoryRegion from ..aliases.LineID import LineID diff --git a/discopop_explorer/pattern_detectors/do_all_detector.py b/discopop_explorer/pattern_detectors/do_all_detector.py index f7768dfb9..75a889f57 100644 --- a/discopop_explorer/pattern_detectors/do_all_detector.py +++ b/discopop_explorer/pattern_detectors/do_all_detector.py @@ -19,8 +19,8 @@ CUNode, LoopNode, PEGraphX, - Node, ) +from ..classes.Node import Node from ..classes.Dependency import Dependency from ..aliases.MemoryRegion import MemoryRegion from ..aliases.LineID import LineID diff --git a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py index bc7a2a575..3304c15a4 100644 --- a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py +++ b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py @@ -15,7 +15,8 @@ from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore from .PatternInfo import PatternInfo -from ..PEGraphX import FunctionNode, LoopNode, PEGraphX, Node +from ..PEGraphX import FunctionNode, LoopNode, PEGraphX +from ..classes.Node import Node from ..aliases.NodeID import NodeID from ..enums.EdgeType import EdgeType from ..utils import classify_task_vars, filter_for_hotspots, get_child_loops diff --git a/discopop_explorer/pattern_detectors/pipeline_detector.py b/discopop_explorer/pattern_detectors/pipeline_detector.py index bd4fadd72..9897ffd5d 100644 --- a/discopop_explorer/pattern_detectors/pipeline_detector.py +++ b/discopop_explorer/pattern_detectors/pipeline_detector.py @@ -17,8 +17,8 @@ CUNode, LoopNode, PEGraphX, - Node, ) +from ..classes.Node import Node from ..classes.Dependency import Dependency from ..aliases.LineID import LineID from ..aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index e5d401fd5..a6a7d64ec 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -19,8 +19,8 @@ CUNode, LoopNode, PEGraphX, - Node, ) +from ..classes.Node import Node from ..classes.Dependency import Dependency from ..aliases.MemoryRegion import MemoryRegion from ..aliases.LineID import LineID diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py index f667ab846..732e7c59c 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py @@ -14,9 +14,9 @@ CUNode, parse_id, FunctionNode, - Node, LoopNode, ) +from ...classes.Node import Node from ...aliases.MemoryRegion import MemoryRegion from ...aliases.LineID import LineID from ...aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py index ec880126b..0d895cc49 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py @@ -12,11 +12,11 @@ from discopop_explorer.PEGraphX import ( PEGraphX, CUNode, - Node, DummyNode, FunctionNode, LoopNode, ) +from discopop_explorer.classes.Node import Node from discopop_explorer.classes.Dependency import Dependency from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.DepType import DepType diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py index 684c43267..0064ae138 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py @@ -14,8 +14,8 @@ PEGraphX, CUNode, LoopNode, - Node, ) +from ...classes.Node import Node from ...aliases.NodeID import NodeID from ...enums.NodeType import NodeType from ...enums.DepType import DepType diff --git a/discopop_explorer/pattern_detectors/task_parallelism/alias_detection.py b/discopop_explorer/pattern_detectors/task_parallelism/alias_detection.py index 736796c80..ae1d729f2 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/alias_detection.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/alias_detection.py @@ -14,6 +14,8 @@ from lxml import objectify # type: ignore +import discopop_explorer.classes.Node + def __prune_statement(stmt_copy: str, statement: str, var_name: str, var_type: str) -> Optional[List[str]]: """splits a statement and performs multiple alias analyses if necessary (more than one '=' contained diff --git a/discopop_explorer/pattern_detectors/task_parallelism/classes.py b/discopop_explorer/pattern_detectors/task_parallelism/classes.py index 8319e5ab6..7d87e4e8c 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/classes.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/classes.py @@ -9,7 +9,8 @@ from enum import Enum from typing import List, Optional -from discopop_explorer.PEGraphX import Node, PEGraphX +from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.MWType import MWType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo diff --git a/discopop_explorer/pattern_detectors/task_parallelism/filter.py b/discopop_explorer/pattern_detectors/task_parallelism/filter.py index 837eecedf..474b4ce50 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/filter.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/filter.py @@ -8,7 +8,8 @@ from typing import List, Dict, cast, Optional, Union -from discopop_explorer.PEGraphX import CUNode, Node, PEGraphX +from discopop_explorer.PEGraphX import CUNode, PEGraphX +from discopop_explorer.classes.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py b/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py index 1e2f35ca6..72f86f013 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py @@ -8,7 +8,8 @@ from typing import List, cast, Dict, Optional, Tuple -from discopop_explorer.PEGraphX import Node, PEGraphX +from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.Node import Node from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.task_parallelism.classes import ( diff --git a/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py b/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py index e636d2db6..1e9c0b3f8 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py @@ -12,6 +12,7 @@ from lxml import objectify, etree # type: ignore +import discopop_explorer.classes.Node from discopop_explorer.PEGraphX import LoopNode, PEGraphX from discopop_explorer.pattern_detectors.task_parallelism.tp_utils import line_contained_in_region diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py index a8d927e66..5ce0ccf21 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py @@ -9,7 +9,8 @@ import copy from typing import List, Tuple, Optional, cast, Dict -from discopop_explorer.PEGraphX import Node, PEGraphX +from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.Node import Node from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py index 6be85a7de..3e4accd25 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py @@ -8,7 +8,8 @@ from typing import List, cast, Tuple, Any -from discopop_explorer.PEGraphX import Node, CUNode, PEGraphX +from discopop_explorer.PEGraphX import CUNode, PEGraphX +from discopop_explorer.classes.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py index 02c8f76aa..7c30c7be4 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py @@ -12,9 +12,9 @@ from discopop_explorer.PEGraphX import ( CUNode, FunctionNode, - Node, PEGraphX, ) +from discopop_explorer.classes.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py index f65ba3795..1e9da8657 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py @@ -12,9 +12,9 @@ CUNode, FunctionNode, LoopNode, - Node, PEGraphX, ) +from discopop_explorer.classes.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.MWType import MWType from discopop_explorer.enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py index 69637aaef..7deeaad06 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py @@ -11,13 +11,14 @@ from lxml import objectify # type: ignore +import discopop_explorer.classes.Node from discopop_explorer.PEGraphX import ( DummyNode, FunctionNode, CUNode, - Node, PEGraphX, ) +from discopop_explorer.classes.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.MWType import MWType diff --git a/discopop_explorer/plugins/pipeline.py b/discopop_explorer/plugins/pipeline.py index 29d11efc1..a97b3d7cc 100644 --- a/discopop_explorer/plugins/pipeline.py +++ b/discopop_explorer/plugins/pipeline.py @@ -9,7 +9,8 @@ from copy import deepcopy from typing import List -from ..PEGraphX import LoopNode, PEGraphX, Node +from ..PEGraphX import LoopNode, PEGraphX +from ..classes.Node import Node from ..aliases.LineID import LineID from ..enums.EdgeType import EdgeType from ..utils import correlation_coefficient diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index bf64a902d..61b4737fa 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -19,8 +19,8 @@ FunctionNode, LoopNode, PEGraphX, - Node, ) +from .classes.Node import Node from .classes.Dependency import Dependency from .aliases.MemoryRegion import MemoryRegion from .aliases.LineID import LineID diff --git a/discopop_library/result_classes/MergedPattern.py b/discopop_library/result_classes/MergedPattern.py index 96e16763d..49efe92c1 100644 --- a/discopop_library/result_classes/MergedPattern.py +++ b/discopop_library/result_classes/MergedPattern.py @@ -9,7 +9,7 @@ import json from typing import Any, Dict, List -from discopop_explorer.PEGraphX import Node +from discopop_explorer.classes.Node import Node from discopop_explorer.pattern_detectors.PatternBase import PatternBase from discopop_library.PatternIdManagement.unique_pattern_id import get_unique_pattern_id diff --git a/discopop_library/result_classes/OptimizerOutputPattern.py b/discopop_library/result_classes/OptimizerOutputPattern.py index 0aabcdf24..6fefaee68 100644 --- a/discopop_library/result_classes/OptimizerOutputPattern.py +++ b/discopop_library/result_classes/OptimizerOutputPattern.py @@ -9,7 +9,7 @@ import json from typing import Any, Dict, List -from discopop_explorer.PEGraphX import Node +from discopop_explorer.classes.Node import Node from discopop_explorer.pattern_detectors.PatternBase import PatternBase from discopop_library.PatternIdManagement.unique_pattern_id import get_unique_pattern_id From fd074555866b267748cdcfc2f7e0bc2f9e5e5148 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 30 Jul 2024 16:49:26 +0200 Subject: [PATCH 056/105] refactor: CUNode --- discopop_explorer/PEGraphX.py | 15 +--------- discopop_explorer/classes/CUNode.py | 29 +++++++++++++++++++ discopop_explorer/generate_Data_CUInst.py | 2 +- .../CombinedGPURegions.py | 3 +- .../combined_gpu_patterns/step_1.py | 3 +- .../combined_gpu_patterns/step_2.py | 2 +- .../combined_gpu_patterns/step_3.py | 3 +- .../combined_gpu_patterns/step_4.py | 2 +- .../combined_gpu_patterns/step_6.py | 2 +- .../pattern_detectors/do_all_detector.py | 2 +- .../pattern_detectors/pipeline_detector.py | 2 +- .../pattern_detectors/reduction_detector.py | 2 +- .../simple_gpu_patterns/GPULoop.py | 2 +- .../simple_gpu_patterns/GPUMemory.py | 2 +- .../simple_gpu_patterns/GPURegions.py | 2 +- .../task_parallelism/filter.py | 3 +- .../task_parallelism/suggesters/barriers.py | 3 +- .../suggesters/dependency_clauses.py | 2 +- .../task_parallelism/suggesters/tasks.py | 2 +- .../task_parallelism/tp_utils.py | 2 +- discopop_explorer/utils.py | 2 +- .../PETParser/DataAccesses/FromCUs.py | 3 +- .../discopop_optimizer/PETParser/PETParser.py | 2 +- 23 files changed, 57 insertions(+), 35 deletions(-) create mode 100644 discopop_explorer/classes/CUNode.py diff --git a/discopop_explorer/PEGraphX.py b/discopop_explorer/PEGraphX.py index 5e442417f..e34fc9de7 100644 --- a/discopop_explorer/PEGraphX.py +++ b/discopop_explorer/PEGraphX.py @@ -23,6 +23,7 @@ from .aliases.LineID import LineID from .aliases.MemoryRegion import MemoryRegion from .aliases.NodeID import NodeID +from .classes.CUNode import CUNode from .classes.Dependency import Dependency from .classes.Node import Node from .enums.DepType import DepType @@ -69,20 +70,6 @@ def parse_id(node_id: str) -> Tuple[int, int]: # raise ValueError("Mal-formatted MemoryRegion identifier: ", id_string) -# Data.xml: type="0" -class CUNode(Node): - instructions_count: int = -1 - basic_block_id = "" - return_instructions_count: int = -1 - local_vars: List[Variable] = [] - global_vars: List[Variable] = [] - performs_file_io: bool = False - - def __init__(self, node_id: NodeID): - super().__init__(node_id) - self.type = NodeType.CU - - # Data.xml: type="2" class LoopNode(Node): loop_iterations: int = -1 diff --git a/discopop_explorer/classes/CUNode.py b/discopop_explorer/classes/CUNode.py new file mode 100644 index 000000000..fe49ac963 --- /dev/null +++ b/discopop_explorer/classes/CUNode.py @@ -0,0 +1,29 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. +from __future__ import annotations + +from typing import List + +from discopop_explorer.aliases.NodeID import NodeID +from discopop_explorer.classes.Node import Node +from discopop_explorer.enums.NodeType import NodeType +from discopop_explorer.variable import Variable + + +# Data.xml: type="0" +class CUNode(Node): + instructions_count: int = -1 + basic_block_id = "" + return_instructions_count: int = -1 + local_vars: List[Variable] = [] + global_vars: List[Variable] = [] + performs_file_io: bool = False + + def __init__(self, node_id: NodeID): + super().__init__(node_id) + self.type = NodeType.CU diff --git a/discopop_explorer/generate_Data_CUInst.py b/discopop_explorer/generate_Data_CUInst.py index 8dd5c39e2..59d8cf6fb 100644 --- a/discopop_explorer/generate_Data_CUInst.py +++ b/discopop_explorer/generate_Data_CUInst.py @@ -10,11 +10,11 @@ from typing import List, cast, TextIO from .PEGraphX import ( - CUNode, FunctionNode, LoopNode, PEGraphX, ) +from .classes.CUNode import CUNode from .classes.Node import Node from .aliases.LineID import LineID from .aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py index e3276d187..ba7a39471 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py @@ -8,7 +8,8 @@ import sys from typing import List, Tuple, Dict, Set, cast -from discopop_explorer.PEGraphX import CUNode, PEGraphX +from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py index c5954d43c..e83a482cb 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py @@ -8,7 +8,8 @@ from typing import List, Tuple, Dict, Set, cast -from discopop_explorer.PEGraphX import PEGraphX, CUNode +from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.DepType import DepType diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py index c12f24d91..68c227166 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py @@ -13,9 +13,9 @@ from discopop_explorer.PEGraphX import ( PEGraphX, - CUNode, FunctionNode, ) +from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.classes.Dependency import Dependency from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py index 0fd7e6b56..a67969b5e 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py @@ -8,7 +8,8 @@ from typing import Dict, List, Tuple, Set, Optional -from discopop_explorer.PEGraphX import PEGraphX, CUNode +from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py index 0b9ad4cfb..7eda0d53e 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py @@ -15,9 +15,9 @@ from discopop_explorer.PEGraphX import ( PEGraphX, - CUNode, FunctionNode, ) +from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.classes.Dependency import Dependency from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py index 6f6464058..5a5c91f22 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py @@ -13,9 +13,9 @@ from discopop_explorer.PEGraphX import ( PEGraphX, - CUNode, FunctionNode, ) +from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.DepType import DepType diff --git a/discopop_explorer/pattern_detectors/do_all_detector.py b/discopop_explorer/pattern_detectors/do_all_detector.py index 75a889f57..780f41a69 100644 --- a/discopop_explorer/pattern_detectors/do_all_detector.py +++ b/discopop_explorer/pattern_detectors/do_all_detector.py @@ -16,10 +16,10 @@ from .PatternInfo import PatternInfo from .reduction_detector import ReductionInfo from ..PEGraphX import ( - CUNode, LoopNode, PEGraphX, ) +from ..classes.CUNode import CUNode from ..classes.Node import Node from ..classes.Dependency import Dependency from ..aliases.MemoryRegion import MemoryRegion diff --git a/discopop_explorer/pattern_detectors/pipeline_detector.py b/discopop_explorer/pattern_detectors/pipeline_detector.py index 9897ffd5d..c367df79e 100644 --- a/discopop_explorer/pattern_detectors/pipeline_detector.py +++ b/discopop_explorer/pattern_detectors/pipeline_detector.py @@ -14,10 +14,10 @@ from .PatternInfo import PatternInfo from ..PEGraphX import ( - CUNode, LoopNode, PEGraphX, ) +from ..classes.CUNode import CUNode from ..classes.Node import Node from ..classes.Dependency import Dependency from ..aliases.LineID import LineID diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index a6a7d64ec..9da31be38 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -16,10 +16,10 @@ from .PatternInfo import PatternInfo from ..PEGraphX import ( - CUNode, LoopNode, PEGraphX, ) +from ..classes.CUNode import CUNode from ..classes.Node import Node from ..classes.Dependency import Dependency from ..aliases.MemoryRegion import MemoryRegion diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py index 732e7c59c..672c4e94e 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py @@ -11,11 +11,11 @@ from discopop_explorer.PEGraphX import ( PEGraphX, - CUNode, parse_id, FunctionNode, LoopNode, ) +from ...classes.CUNode import CUNode from ...classes.Node import Node from ...aliases.MemoryRegion import MemoryRegion from ...aliases.LineID import LineID diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py index 0d895cc49..3c81051a8 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py @@ -11,11 +11,11 @@ from discopop_explorer.PEGraphX import ( PEGraphX, - CUNode, DummyNode, FunctionNode, LoopNode, ) +from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.classes.Node import Node from discopop_explorer.classes.Dependency import Dependency from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py index 0064ae138..7439ab8ef 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py @@ -12,9 +12,9 @@ from discopop_explorer.PEGraphX import ( PEGraphX, - CUNode, LoopNode, ) +from ...classes.CUNode import CUNode from ...classes.Node import Node from ...aliases.NodeID import NodeID from ...enums.NodeType import NodeType diff --git a/discopop_explorer/pattern_detectors/task_parallelism/filter.py b/discopop_explorer/pattern_detectors/task_parallelism/filter.py index 474b4ce50..3ac38c0d7 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/filter.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/filter.py @@ -8,7 +8,8 @@ from typing import List, Dict, cast, Optional, Union -from discopop_explorer.PEGraphX import CUNode, PEGraphX +from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.classes.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.NodeType import NodeType diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py index 3e4accd25..db4cc5f6a 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py @@ -8,7 +8,8 @@ from typing import List, cast, Tuple, Any -from discopop_explorer.PEGraphX import CUNode, PEGraphX +from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.classes.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.NodeType import NodeType diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py index 7c30c7be4..35e01ac9e 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py @@ -10,10 +10,10 @@ from typing import List, Dict, Tuple, Optional, cast, Any from discopop_explorer.PEGraphX import ( - CUNode, FunctionNode, PEGraphX, ) +from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.classes.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py index 1e9da8657..56b49cc1c 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py @@ -9,11 +9,11 @@ from typing import List, Dict, cast from discopop_explorer.PEGraphX import ( - CUNode, FunctionNode, LoopNode, PEGraphX, ) +from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.classes.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.MWType import MWType diff --git a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py index 7deeaad06..918e9eb72 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py @@ -15,9 +15,9 @@ from discopop_explorer.PEGraphX import ( DummyNode, FunctionNode, - CUNode, PEGraphX, ) +from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.classes.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.NodeType import NodeType diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index 61b4737fa..296da5924 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -15,11 +15,11 @@ from discopop_library.HostpotLoader.HotspotType import HotspotType from .PEGraphX import ( - CUNode, FunctionNode, LoopNode, PEGraphX, ) +from .classes.CUNode import CUNode from .classes.Node import Node from .classes.Dependency import Dependency from .aliases.MemoryRegion import MemoryRegion diff --git a/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py b/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py index 94939717a..767118488 100644 --- a/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py +++ b/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py @@ -7,7 +7,8 @@ # directory for details. from typing import Tuple, Set, cast -from discopop_explorer.PEGraphX import PEGraphX, CUNode +from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.DepType import DepType diff --git a/discopop_library/discopop_optimizer/PETParser/PETParser.py b/discopop_library/discopop_optimizer/PETParser/PETParser.py index 134232b40..f18159811 100644 --- a/discopop_library/discopop_optimizer/PETParser/PETParser.py +++ b/discopop_library/discopop_optimizer/PETParser/PETParser.py @@ -20,8 +20,8 @@ PEGraphX, FunctionNode, LoopNode, - CUNode, ) +from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType From 160e63be6ca90409088e861685bd9cd858cb39cc Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 30 Jul 2024 16:52:42 +0200 Subject: [PATCH 057/105] refactor: FunctionNode and LoopNode --- discopop_explorer/PEGraphX.py | 219 +----------------- discopop_explorer/classes/DummyNode.py | 24 ++ discopop_explorer/classes/FunctionNode.py | 165 +++++++++++++ discopop_explorer/classes/LoopNode.py | 82 +++++++ discopop_explorer/classes/Node.py | 3 +- discopop_explorer/generate_Data_CUInst.py | 4 +- discopop_explorer/parallel_utils.py | 3 +- discopop_explorer/pattern_detection.py | 4 +- .../pattern_detectors/PatternInfo.py | 3 +- .../combined_gpu_patterns/step_2.py | 2 +- .../combined_gpu_patterns/step_4.py | 2 +- .../combined_gpu_patterns/step_6.py | 2 +- .../combined_gpu_patterns/utilities.py | 2 +- .../pattern_detectors/do_all_detector.py | 2 +- .../geometric_decomposition_detector.py | 4 +- .../pattern_detectors/pipeline_detector.py | 2 +- .../pattern_detectors/reduction_detector.py | 2 +- .../simple_gpu_patterns/GPULoop.py | 4 +- .../simple_gpu_patterns/GPUMemory.py | 6 +- .../simple_gpu_patterns/GPURegions.py | 2 +- .../gpu_pattern_detector.py | 3 +- .../task_parallelism/preprocessor.py | 3 +- .../suggesters/data_sharing_clauses.py | 3 +- .../suggesters/dependency_clauses.py | 2 +- .../task_parallelism/suggesters/tasks.py | 4 +- .../task_parallelism_detector.py | 3 +- .../task_parallelism/tp_utils.py | 4 +- discopop_explorer/plugins/pipeline.py | 3 +- discopop_explorer/utils.py | 4 +- .../EmpiricalAutotuning/Autotuner.py | 2 +- .../discopop_optimizer/PETParser/PETParser.py | 4 +- .../RemoveLoopIndexUpdates.py | 2 +- 32 files changed, 322 insertions(+), 252 deletions(-) create mode 100644 discopop_explorer/classes/DummyNode.py create mode 100644 discopop_explorer/classes/FunctionNode.py create mode 100644 discopop_explorer/classes/LoopNode.py diff --git a/discopop_explorer/PEGraphX.py b/discopop_explorer/PEGraphX.py index e34fc9de7..a6d46afcc 100644 --- a/discopop_explorer/PEGraphX.py +++ b/discopop_explorer/PEGraphX.py @@ -25,6 +25,9 @@ from .aliases.NodeID import NodeID from .classes.CUNode import CUNode from .classes.Dependency import Dependency +from .classes.DummyNode import DummyNode +from .classes.FunctionNode import FunctionNode +from .classes.LoopNode import LoopNode from .classes.Node import Node from .enums.DepType import DepType from .enums.EdgeType import EdgeType @@ -70,222 +73,6 @@ def parse_id(node_id: str) -> Tuple[int, int]: # raise ValueError("Mal-formatted MemoryRegion identifier: ", id_string) -# Data.xml: type="2" -class LoopNode(Node): - loop_iterations: int = -1 - contains_array_reduction: bool = False - loop_data: Optional[LoopData] - loop_indices: List[str] - - def __init__(self, node_id: NodeID): - super().__init__(node_id) - self.type = NodeType.LOOP - self.loop_indices = [] - - def get_nesting_level(self, pet: PEGraphX, return_invert_result: bool = True) -> int: - """Returns the loop nesting level for the given loop node. - Currently, due to the profiling output, only 3 nesting levels of loops can be mapped correctly. - Innermost level is 0. - Outermost (maximum) level is 2. - The order of the results originates from the LoopStack used during the profiling. - - Example: - main(){ - for(){ // level 1 - for(){} // level 0 - } - } - """ - parents = [s for s, t, d in pet.in_edges(self.id, EdgeType.CHILD)] - - # count levels upwards - parent_nesting_levels: List[int] = [] - for parent_id in parents: - parent_node = pet.node_at(parent_id) - if type(parent_node) == FunctionNode: - # loop is a direct child of a function node --> Nesting level 0 - parent_nesting_levels.append(0) - break - elif type(parent_node) == LoopNode: - parent_nesting_levels.append( - min( - 2, - parent_node.get_nesting_level(pet, return_invert_result=False), - ) - ) - - if return_invert_result: - # invert the leveling and cutoff at 0 - inverted_levels = [max(0, 2 - level) for level in parent_nesting_levels] - return min(inverted_levels) - else: - return max(parent_nesting_levels) - - def get_entry_node(self, pet: PEGraphX) -> Optional[Node]: - """returns the first CU Node contained in the loop (i.e. one without predecessor inside the loop)""" - for node in pet.direct_children(self): - predecessors_outside_loop_body = [ - s - for s, t, d in pet.in_edges(node.id, EdgeType.SUCCESSOR) - if pet.node_at(s) not in pet.direct_children(self) - ] - if len(predecessors_outside_loop_body) > 0: - return node - return None - - -# Data.xml: type="3" -class DummyNode(Node): - args: List[Variable] = [] - - def __init__(self, node_id: NodeID): - super().__init__(node_id) - self.type = NodeType.DUMMY - - -# Data.xml: type="1" -class FunctionNode(Node): - args: List[Variable] = [] - children_cu_ids: Optional[List[NodeID]] = None # metadata to speedup some calculations - reachability_pairs: Dict[NodeID, Set[NodeID]] - immediate_post_dominators: Dict[NodeID, NodeID] - immediate_post_dominators_present: bool - memory_accesses: Dict[int, Dict[MemoryRegion, Set[Optional[int]]]] - memory_accesses_present: bool - - def __init__(self, node_id: NodeID): - super().__init__(node_id) - self.type = NodeType.FUNC - self.reachability_pairs = dict() - self.immediate_post_dominators_present = False - self.memory_accesses_present = False - - def get_entry_cu_id(self, pet: PEGraphX) -> NodeID: - for child_cu_id in [t for s, t, d in pet.out_edges(self.id, EdgeType.CHILD)]: - if len(pet.in_edges(child_cu_id, EdgeType.SUCCESSOR)) == 0: - return child_cu_id - raise ValueError("Mal-formatted function: ", self.id, " - No entry CU found!") - - def get_exit_cu_ids(self, pet: PEGraphX) -> Set[NodeID]: - exit_cu_ids: Set[NodeID] = set() - if self.children_cu_ids is not None: - for child_cu_id in self.children_cu_ids: - if ( - len(pet.out_edges(child_cu_id, EdgeType.SUCCESSOR)) == 0 - and len(pet.in_edges(child_cu_id, EdgeType.SUCCESSOR)) != 0 - ): - exit_cu_ids.add(child_cu_id) - return exit_cu_ids - - def calculate_reachability_pairs(self, pet: PEGraphX) -> Dict[NodeID, Set[NodeID]]: - reachability_pairs: Dict[NodeID, Set[NodeID]] = dict() - # create graph copy and remove all but successor edges - copied_graph = pet.g.copy() - - # remove all but successor edges - to_be_removed = set() - for edge in copied_graph.edges: - edge_data = cast(Dependency, copied_graph.edges[edge]["data"]) - if edge_data.etype != EdgeType.SUCCESSOR: - to_be_removed.add(edge) - for edge in to_be_removed: - copied_graph.remove_edge(edge[0], edge[1]) - - # calculate dfs successors for children CUs - for node_id in cast(List[NodeID], self.children_cu_ids): - reachability_pairs[node_id] = {node_id} - successors = [t for s, t in nx.dfs_tree(copied_graph, node_id).edges()] - reachability_pairs[node_id].update(successors) - return reachability_pairs - - def get_immediate_post_dominators(self, pet: PEGraphX) -> Dict[NodeID, NodeID]: - if self.immediate_post_dominators_present: - import sys - - print("METADATA HIT! ", self.node_id, file=sys.stderr) - return self.immediate_post_dominators - else: - # copy graph since edges need to be removed - copied_graph = pet.g.copy() - exit_cu_ids = self.get_exit_cu_ids(pet) - # remove all but successor edges - to_be_removed = set() - for edge in copied_graph.edges: - edge_data = cast(Dependency, copied_graph.edges[edge]["data"]) - if edge_data.etype != EdgeType.SUCCESSOR: - to_be_removed.add(edge) - for edge in to_be_removed: - copied_graph.remove_edge(edge[0], edge[1]) - - # reverse edges - immediate_post_dominators: Set[Tuple[NodeID, NodeID]] = set() - for exit_cu_id in exit_cu_ids: - immediate_post_dominators.update(nx.immediate_dominators(copied_graph.reverse(), exit_cu_id).items()) - - immediate_post_dominators_dict = dict(immediate_post_dominators) - # add trivial cases for missing modes - for child_id in cast(List[NodeID], self.children_cu_ids): - if child_id not in immediate_post_dominators_dict: - immediate_post_dominators_dict[child_id] = child_id - - # initialize result dictionary and add trivial cases for all children - self.immediate_post_dominators = dict() - for child_id in cast(List[NodeID], self.children_cu_ids): - if child_id not in self.immediate_post_dominators: - self.immediate_post_dominators[child_id] = child_id - - # find post dominator outside parent, if type(parent) != function - for node_id in cast(List[NodeID], self.children_cu_ids): - if type(pet.node_at(node_id)) != CUNode: - continue - # initialize search with immediate post dominator - post_dom_id = immediate_post_dominators_dict[node_id] - visited = set() - use_original = False - while ( - pet.node_at(node_id).get_parent_id(pet) == pet.node_at(post_dom_id).get_parent_id(pet) - and type(pet.node_at(cast(NodeID, pet.node_at(post_dom_id).get_parent_id(pet)))) != FunctionNode - ): - if post_dom_id in visited: - # cycle detected! - use_original = True - break - - visited.add(post_dom_id) - new_post_dom_id = immediate_post_dominators_dict[post_dom_id] - import sys - - print("Post dom: ", post_dom_id, file=sys.stderr) - print("New post dom: ", new_post_dom_id, file=sys.stderr) - print(file=sys.stderr) - if post_dom_id == new_post_dom_id: - break - post_dom_id = new_post_dom_id - if not use_original: - # found post dom - self.immediate_post_dominators[node_id] = post_dom_id - self.immediate_post_dominators_present = True - return self.immediate_post_dominators - - def get_memory_accesses( - self, writes_by_device: Dict[int, Dict[NodeID, Dict[MemoryRegion, Set[Optional[int]]]]] - ) -> Dict[int, Dict[MemoryRegion, Set[Optional[int]]]]: - if not self.memory_accesses_present: - self.memory_accesses = dict() - self.memory_accesses_present = True - - for child_id in cast(List[NodeID], self.children_cu_ids): - for device_id in writes_by_device: - if device_id not in self.memory_accesses: - self.memory_accesses[device_id] = dict() - if child_id in writes_by_device[device_id]: - for mem_reg in writes_by_device[device_id][child_id]: - if mem_reg not in self.memory_accesses[device_id]: - self.memory_accesses[device_id][mem_reg] = set() - self.memory_accesses[device_id][mem_reg].update(writes_by_device[device_id][child_id][mem_reg]) - return self.memory_accesses - - def parse_cu(node: ObjectifiedElement) -> Node: node_id = node.get("id") node_type = NodeType(int(node.get("type"))) diff --git a/discopop_explorer/classes/DummyNode.py b/discopop_explorer/classes/DummyNode.py new file mode 100644 index 000000000..8685379c4 --- /dev/null +++ b/discopop_explorer/classes/DummyNode.py @@ -0,0 +1,24 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. +from __future__ import annotations + +from typing import List + +from discopop_explorer.aliases.NodeID import NodeID +from discopop_explorer.classes.Node import Node +from discopop_explorer.enums.NodeType import NodeType +from discopop_explorer.variable import Variable + + +# Data.xml: type="3" +class DummyNode(Node): + args: List[Variable] = [] + + def __init__(self, node_id: NodeID): + super().__init__(node_id) + self.type = NodeType.DUMMY diff --git a/discopop_explorer/classes/FunctionNode.py b/discopop_explorer/classes/FunctionNode.py new file mode 100644 index 000000000..c84c9dc4a --- /dev/null +++ b/discopop_explorer/classes/FunctionNode.py @@ -0,0 +1,165 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. +from __future__ import annotations + +from typing import List, Optional, Dict, Set, cast, Tuple + +import networkx as nx + +from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.aliases.MemoryRegion import MemoryRegion +from discopop_explorer.aliases.NodeID import NodeID +from discopop_explorer.classes.CUNode import CUNode +from discopop_explorer.classes.Dependency import Dependency +from discopop_explorer.classes.Node import Node +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.enums.NodeType import NodeType +from discopop_explorer.variable import Variable + + +# Data.xml: type="1" +class FunctionNode(Node): + args: List[Variable] = [] + children_cu_ids: Optional[List[NodeID]] = None # metadata to speedup some calculations + reachability_pairs: Dict[NodeID, Set[NodeID]] + immediate_post_dominators: Dict[NodeID, NodeID] + immediate_post_dominators_present: bool + memory_accesses: Dict[int, Dict[MemoryRegion, Set[Optional[int]]]] + memory_accesses_present: bool + + def __init__(self, node_id: NodeID): + super().__init__(node_id) + self.type = NodeType.FUNC + self.reachability_pairs = dict() + self.immediate_post_dominators_present = False + self.memory_accesses_present = False + + def get_entry_cu_id(self, pet: PEGraphX) -> NodeID: + for child_cu_id in [t for s, t, d in pet.out_edges(self.id, EdgeType.CHILD)]: + if len(pet.in_edges(child_cu_id, EdgeType.SUCCESSOR)) == 0: + return child_cu_id + raise ValueError("Mal-formatted function: ", self.id, " - No entry CU found!") + + def get_exit_cu_ids(self, pet: PEGraphX) -> Set[NodeID]: + exit_cu_ids: Set[NodeID] = set() + if self.children_cu_ids is not None: + for child_cu_id in self.children_cu_ids: + if ( + len(pet.out_edges(child_cu_id, EdgeType.SUCCESSOR)) == 0 + and len(pet.in_edges(child_cu_id, EdgeType.SUCCESSOR)) != 0 + ): + exit_cu_ids.add(child_cu_id) + return exit_cu_ids + + def calculate_reachability_pairs(self, pet: PEGraphX) -> Dict[NodeID, Set[NodeID]]: + reachability_pairs: Dict[NodeID, Set[NodeID]] = dict() + # create graph copy and remove all but successor edges + copied_graph = pet.g.copy() + + # remove all but successor edges + to_be_removed = set() + for edge in copied_graph.edges: + edge_data = cast(Dependency, copied_graph.edges[edge]["data"]) + if edge_data.etype != EdgeType.SUCCESSOR: + to_be_removed.add(edge) + for edge in to_be_removed: + copied_graph.remove_edge(edge[0], edge[1]) + + # calculate dfs successors for children CUs + for node_id in cast(List[NodeID], self.children_cu_ids): + reachability_pairs[node_id] = {node_id} + successors = [t for s, t in nx.dfs_tree(copied_graph, node_id).edges()] + reachability_pairs[node_id].update(successors) + return reachability_pairs + + def get_immediate_post_dominators(self, pet: PEGraphX) -> Dict[NodeID, NodeID]: + if self.immediate_post_dominators_present: + import sys + + print("METADATA HIT! ", self.node_id, file=sys.stderr) + return self.immediate_post_dominators + else: + # copy graph since edges need to be removed + copied_graph = pet.g.copy() + exit_cu_ids = self.get_exit_cu_ids(pet) + # remove all but successor edges + to_be_removed = set() + for edge in copied_graph.edges: + edge_data = cast(Dependency, copied_graph.edges[edge]["data"]) + if edge_data.etype != EdgeType.SUCCESSOR: + to_be_removed.add(edge) + for edge in to_be_removed: + copied_graph.remove_edge(edge[0], edge[1]) + + # reverse edges + immediate_post_dominators: Set[Tuple[NodeID, NodeID]] = set() + for exit_cu_id in exit_cu_ids: + immediate_post_dominators.update(nx.immediate_dominators(copied_graph.reverse(), exit_cu_id).items()) + + immediate_post_dominators_dict = dict(immediate_post_dominators) + # add trivial cases for missing modes + for child_id in cast(List[NodeID], self.children_cu_ids): + if child_id not in immediate_post_dominators_dict: + immediate_post_dominators_dict[child_id] = child_id + + # initialize result dictionary and add trivial cases for all children + self.immediate_post_dominators = dict() + for child_id in cast(List[NodeID], self.children_cu_ids): + if child_id not in self.immediate_post_dominators: + self.immediate_post_dominators[child_id] = child_id + + # find post dominator outside parent, if type(parent) != function + for node_id in cast(List[NodeID], self.children_cu_ids): + if type(pet.node_at(node_id)) != CUNode: + continue + # initialize search with immediate post dominator + post_dom_id = immediate_post_dominators_dict[node_id] + visited = set() + use_original = False + while ( + pet.node_at(node_id).get_parent_id(pet) == pet.node_at(post_dom_id).get_parent_id(pet) + and type(pet.node_at(cast(NodeID, pet.node_at(post_dom_id).get_parent_id(pet)))) != FunctionNode + ): + if post_dom_id in visited: + # cycle detected! + use_original = True + break + + visited.add(post_dom_id) + new_post_dom_id = immediate_post_dominators_dict[post_dom_id] + import sys + + print("Post dom: ", post_dom_id, file=sys.stderr) + print("New post dom: ", new_post_dom_id, file=sys.stderr) + print(file=sys.stderr) + if post_dom_id == new_post_dom_id: + break + post_dom_id = new_post_dom_id + if not use_original: + # found post dom + self.immediate_post_dominators[node_id] = post_dom_id + self.immediate_post_dominators_present = True + return self.immediate_post_dominators + + def get_memory_accesses( + self, writes_by_device: Dict[int, Dict[NodeID, Dict[MemoryRegion, Set[Optional[int]]]]] + ) -> Dict[int, Dict[MemoryRegion, Set[Optional[int]]]]: + if not self.memory_accesses_present: + self.memory_accesses = dict() + self.memory_accesses_present = True + + for child_id in cast(List[NodeID], self.children_cu_ids): + for device_id in writes_by_device: + if device_id not in self.memory_accesses: + self.memory_accesses[device_id] = dict() + if child_id in writes_by_device[device_id]: + for mem_reg in writes_by_device[device_id][child_id]: + if mem_reg not in self.memory_accesses[device_id]: + self.memory_accesses[device_id][mem_reg] = set() + self.memory_accesses[device_id][mem_reg].update(writes_by_device[device_id][child_id][mem_reg]) + return self.memory_accesses diff --git a/discopop_explorer/classes/LoopNode.py b/discopop_explorer/classes/LoopNode.py new file mode 100644 index 000000000..7f2347496 --- /dev/null +++ b/discopop_explorer/classes/LoopNode.py @@ -0,0 +1,82 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. +from __future__ import annotations + +from typing import Optional, List + +from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.FunctionNode import FunctionNode +from discopop_explorer.aliases.NodeID import NodeID +from discopop_explorer.classes.Node import Node +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.enums.NodeType import NodeType +from discopop_explorer.parser import LoopData + + +# Data.xml: type="2" +class LoopNode(Node): + loop_iterations: int = -1 + contains_array_reduction: bool = False + loop_data: Optional[LoopData] + loop_indices: List[str] + + def __init__(self, node_id: NodeID): + super().__init__(node_id) + self.type = NodeType.LOOP + self.loop_indices = [] + + def get_nesting_level(self, pet: PEGraphX, return_invert_result: bool = True) -> int: + """Returns the loop nesting level for the given loop node. + Currently, due to the profiling output, only 3 nesting levels of loops can be mapped correctly. + Innermost level is 0. + Outermost (maximum) level is 2. + The order of the results originates from the LoopStack used during the profiling. + + Example: + main(){ + for(){ // level 1 + for(){} // level 0 + } + } + """ + parents = [s for s, t, d in pet.in_edges(self.id, EdgeType.CHILD)] + + # count levels upwards + parent_nesting_levels: List[int] = [] + for parent_id in parents: + parent_node = pet.node_at(parent_id) + if type(parent_node) == FunctionNode: + # loop is a direct child of a function node --> Nesting level 0 + parent_nesting_levels.append(0) + break + elif type(parent_node) == LoopNode: + parent_nesting_levels.append( + min( + 2, + parent_node.get_nesting_level(pet, return_invert_result=False), + ) + ) + + if return_invert_result: + # invert the leveling and cutoff at 0 + inverted_levels = [max(0, 2 - level) for level in parent_nesting_levels] + return min(inverted_levels) + else: + return max(parent_nesting_levels) + + def get_entry_node(self, pet: PEGraphX) -> Optional[Node]: + """returns the first CU Node contained in the loop (i.e. one without predecessor inside the loop)""" + for node in pet.direct_children(self): + predecessors_outside_loop_body = [ + s + for s, t, d in pet.in_edges(node.id, EdgeType.SUCCESSOR) + if pet.node_at(s) not in pet.direct_children(self) + ] + if len(predecessors_outside_loop_body) > 0: + return node + return None diff --git a/discopop_explorer/classes/Node.py b/discopop_explorer/classes/Node.py index d8ab0baaf..b1f4c0235 100644 --- a/discopop_explorer/classes/Node.py +++ b/discopop_explorer/classes/Node.py @@ -9,7 +9,8 @@ from typing import Optional, List, Dict, Any -from discopop_explorer.PEGraphX import parse_id, PEGraphX, FunctionNode +from discopop_explorer.PEGraphX import parse_id, PEGraphX +from discopop_explorer.classes.FunctionNode import FunctionNode from discopop_explorer.aliases.LineID import LineID from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType diff --git a/discopop_explorer/generate_Data_CUInst.py b/discopop_explorer/generate_Data_CUInst.py index 59d8cf6fb..3a936aee9 100644 --- a/discopop_explorer/generate_Data_CUInst.py +++ b/discopop_explorer/generate_Data_CUInst.py @@ -10,10 +10,10 @@ from typing import List, cast, TextIO from .PEGraphX import ( - FunctionNode, - LoopNode, PEGraphX, ) +from .classes.FunctionNode import FunctionNode +from .classes.LoopNode import LoopNode from .classes.CUNode import CUNode from .classes.Node import Node from .aliases.LineID import LineID diff --git a/discopop_explorer/parallel_utils.py b/discopop_explorer/parallel_utils.py index cb8b02658..ab709f818 100644 --- a/discopop_explorer/parallel_utils.py +++ b/discopop_explorer/parallel_utils.py @@ -6,7 +6,8 @@ # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. -from .PEGraphX import FunctionNode, PEGraphX +from .PEGraphX import PEGraphX +from .classes.FunctionNode import FunctionNode from .classes.Node import Node from .aliases.NodeID import NodeID from typing import Any, List, Optional, Set, Tuple diff --git a/discopop_explorer/pattern_detection.py b/discopop_explorer/pattern_detection.py index aed7b74ee..da6e750c3 100644 --- a/discopop_explorer/pattern_detection.py +++ b/discopop_explorer/pattern_detection.py @@ -28,7 +28,9 @@ ) from discopop_library.discopop_optimizer.utilities.MOGUtilities import get_nodes_from_cu_id from discopop_library.result_classes.DetectionResult import DetectionResult -from .PEGraphX import DummyNode, LoopNode, PEGraphX +from .PEGraphX import PEGraphX +from .classes.DummyNode import DummyNode +from .classes.LoopNode import LoopNode from .aliases.NodeID import NodeID from .enums.EdgeType import EdgeType from .pattern_detectors.do_all_detector import DoAllInfo, run_detection as detect_do_all diff --git a/discopop_explorer/pattern_detectors/PatternInfo.py b/discopop_explorer/pattern_detectors/PatternInfo.py index 7364b27e1..dda9d7902 100644 --- a/discopop_explorer/pattern_detectors/PatternInfo.py +++ b/discopop_explorer/pattern_detectors/PatternInfo.py @@ -12,7 +12,8 @@ from discopop_library.discopop_optimizer.classes.system.devices.DeviceTypeEnum import DeviceTypeEnum -from ..PEGraphX import LoopNode, PEGraphX +from ..PEGraphX import PEGraphX +from ..classes.LoopNode import LoopNode from ..classes.Node import Node from ..aliases.LineID import LineID from ..aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py index 68c227166..3671e3ed9 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py @@ -13,8 +13,8 @@ from discopop_explorer.PEGraphX import ( PEGraphX, - FunctionNode, ) +from discopop_explorer.classes.FunctionNode import FunctionNode from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.classes.Dependency import Dependency from discopop_explorer.aliases.MemoryRegion import MemoryRegion diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py index 7eda0d53e..f24e2689f 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py @@ -15,8 +15,8 @@ from discopop_explorer.PEGraphX import ( PEGraphX, - FunctionNode, ) +from discopop_explorer.classes.FunctionNode import FunctionNode from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.classes.Dependency import Dependency from discopop_explorer.aliases.MemoryRegion import MemoryRegion diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py index 5a5c91f22..5fb50ba6b 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py @@ -13,8 +13,8 @@ from discopop_explorer.PEGraphX import ( PEGraphX, - FunctionNode, ) +from discopop_explorer.classes.FunctionNode import FunctionNode from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py index 3bcf105a9..80f69fec6 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py @@ -10,8 +10,8 @@ from discopop_explorer.PEGraphX import ( PEGraphX, - FunctionNode, ) +from discopop_explorer.classes.FunctionNode import FunctionNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/do_all_detector.py b/discopop_explorer/pattern_detectors/do_all_detector.py index 780f41a69..5d02db75e 100644 --- a/discopop_explorer/pattern_detectors/do_all_detector.py +++ b/discopop_explorer/pattern_detectors/do_all_detector.py @@ -16,9 +16,9 @@ from .PatternInfo import PatternInfo from .reduction_detector import ReductionInfo from ..PEGraphX import ( - LoopNode, PEGraphX, ) +from ..classes.LoopNode import LoopNode from ..classes.CUNode import CUNode from ..classes.Node import Node from ..classes.Dependency import Dependency diff --git a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py index 3304c15a4..6a5480efb 100644 --- a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py +++ b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py @@ -15,7 +15,9 @@ from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore from .PatternInfo import PatternInfo -from ..PEGraphX import FunctionNode, LoopNode, PEGraphX +from ..PEGraphX import PEGraphX +from ..classes.FunctionNode import FunctionNode +from ..classes.LoopNode import LoopNode from ..classes.Node import Node from ..aliases.NodeID import NodeID from ..enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/pipeline_detector.py b/discopop_explorer/pattern_detectors/pipeline_detector.py index c367df79e..809275923 100644 --- a/discopop_explorer/pattern_detectors/pipeline_detector.py +++ b/discopop_explorer/pattern_detectors/pipeline_detector.py @@ -14,9 +14,9 @@ from .PatternInfo import PatternInfo from ..PEGraphX import ( - LoopNode, PEGraphX, ) +from ..classes.LoopNode import LoopNode from ..classes.CUNode import CUNode from ..classes.Node import Node from ..classes.Dependency import Dependency diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index 9da31be38..307973669 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -16,9 +16,9 @@ from .PatternInfo import PatternInfo from ..PEGraphX import ( - LoopNode, PEGraphX, ) +from ..classes.LoopNode import LoopNode from ..classes.CUNode import CUNode from ..classes.Node import Node from ..classes.Dependency import Dependency diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py index 672c4e94e..0fe6909e3 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py @@ -12,9 +12,9 @@ from discopop_explorer.PEGraphX import ( PEGraphX, parse_id, - FunctionNode, - LoopNode, ) +from ...classes.FunctionNode import FunctionNode +from ...classes.LoopNode import LoopNode from ...classes.CUNode import CUNode from ...classes.Node import Node from ...aliases.MemoryRegion import MemoryRegion diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py index 3c81051a8..cce7ee88b 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py @@ -11,10 +11,10 @@ from discopop_explorer.PEGraphX import ( PEGraphX, - DummyNode, - FunctionNode, - LoopNode, ) +from discopop_explorer.classes.FunctionNode import FunctionNode +from discopop_explorer.classes.DummyNode import DummyNode +from discopop_explorer.classes.LoopNode import LoopNode from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.classes.Node import Node from discopop_explorer.classes.Dependency import Dependency diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py index 7439ab8ef..adfdccd92 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py @@ -12,8 +12,8 @@ from discopop_explorer.PEGraphX import ( PEGraphX, - LoopNode, ) +from ...classes.LoopNode import LoopNode from ...classes.CUNode import CUNode from ...classes.Node import Node from ...aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py index 1461a49ae..ace093359 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py @@ -10,7 +10,8 @@ from alive_progress import alive_bar # type: ignore -from discopop_explorer.PEGraphX import PEGraphX, LoopNode +from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.LoopNode import LoopNode from discopop_explorer.aliases.LineID import LineID from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.simple_gpu_patterns.GPULoop import GPULoopPattern diff --git a/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py b/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py index 1e9c0b3f8..8449f9c39 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py @@ -13,7 +13,8 @@ from lxml import objectify, etree # type: ignore import discopop_explorer.classes.Node -from discopop_explorer.PEGraphX import LoopNode, PEGraphX +from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.LoopNode import LoopNode from discopop_explorer.pattern_detectors.task_parallelism.tp_utils import line_contained_in_region diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py index 77d8db97a..b33243cd3 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py @@ -8,7 +8,8 @@ from typing import List -from discopop_explorer.PEGraphX import FunctionNode, PEGraphX +from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.FunctionNode import FunctionNode from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.task_parallelism.classes import ( diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py index 35e01ac9e..118287085 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py @@ -10,9 +10,9 @@ from typing import List, Dict, Tuple, Optional, cast, Any from discopop_explorer.PEGraphX import ( - FunctionNode, PEGraphX, ) +from discopop_explorer.classes.FunctionNode import FunctionNode from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.classes.Node import Node from discopop_explorer.aliases.LineID import LineID diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py index 56b49cc1c..ffd60725c 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py @@ -9,10 +9,10 @@ from typing import List, Dict, cast from discopop_explorer.PEGraphX import ( - FunctionNode, - LoopNode, PEGraphX, ) +from discopop_explorer.classes.FunctionNode import FunctionNode +from discopop_explorer.classes.LoopNode import LoopNode from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.classes.Node import Node from discopop_explorer.aliases.LineID import LineID diff --git a/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py b/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py index 415f1f47a..48e6da52d 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py @@ -9,7 +9,8 @@ from typing import Dict, List, Optional, Tuple, cast -from discopop_explorer.PEGraphX import DummyNode, PEGraphX +from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.DummyNode import DummyNode from discopop_explorer.enums.MWType import MWType from discopop_explorer.parser import parse_inputs from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo diff --git a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py index 918e9eb72..66c8c5466 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py @@ -13,10 +13,10 @@ import discopop_explorer.classes.Node from discopop_explorer.PEGraphX import ( - DummyNode, - FunctionNode, PEGraphX, ) +from discopop_explorer.classes.FunctionNode import FunctionNode +from discopop_explorer.classes.DummyNode import DummyNode from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.classes.Node import Node from discopop_explorer.aliases.LineID import LineID diff --git a/discopop_explorer/plugins/pipeline.py b/discopop_explorer/plugins/pipeline.py index a97b3d7cc..04eca0899 100644 --- a/discopop_explorer/plugins/pipeline.py +++ b/discopop_explorer/plugins/pipeline.py @@ -9,7 +9,8 @@ from copy import deepcopy from typing import List -from ..PEGraphX import LoopNode, PEGraphX +from ..PEGraphX import PEGraphX +from ..classes.LoopNode import LoopNode from ..classes.Node import Node from ..aliases.LineID import LineID from ..enums.EdgeType import EdgeType diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index 296da5924..2c9288d06 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -15,10 +15,10 @@ from discopop_library.HostpotLoader.HotspotType import HotspotType from .PEGraphX import ( - FunctionNode, - LoopNode, PEGraphX, ) +from .classes.FunctionNode import FunctionNode +from .classes.LoopNode import LoopNode from .classes.CUNode import CUNode from .classes.Node import Node from .classes.Dependency import Dependency diff --git a/discopop_library/EmpiricalAutotuning/Autotuner.py b/discopop_library/EmpiricalAutotuning/Autotuner.py index 374497c3b..624522ace 100644 --- a/discopop_library/EmpiricalAutotuning/Autotuner.py +++ b/discopop_library/EmpiricalAutotuning/Autotuner.py @@ -11,7 +11,7 @@ from typing import List, Optional, Set, Tuple, cast import jsonpickle # type: ignore -from discopop_explorer.PEGraphX import LoopNode +from discopop_explorer.classes.LoopNode import LoopNode from discopop_library.EmpiricalAutotuning.ArgumentClasses import AutotunerArguments from discopop_library.EmpiricalAutotuning.Classes.CodeConfiguration import CodeConfiguration from discopop_library.EmpiricalAutotuning.Classes.ExecutionResult import ExecutionResult diff --git a/discopop_library/discopop_optimizer/PETParser/PETParser.py b/discopop_library/discopop_optimizer/PETParser/PETParser.py index f18159811..15757804c 100644 --- a/discopop_library/discopop_optimizer/PETParser/PETParser.py +++ b/discopop_library/discopop_optimizer/PETParser/PETParser.py @@ -18,9 +18,9 @@ from discopop_explorer.PEGraphX import ( PEGraphX, - FunctionNode, - LoopNode, ) +from discopop_explorer.classes.FunctionNode import FunctionNode +from discopop_explorer.classes.LoopNode import LoopNode from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_library/discopop_optimizer/UpdateOptimization/RemoveLoopIndexUpdates.py b/discopop_library/discopop_optimizer/UpdateOptimization/RemoveLoopIndexUpdates.py index 0065156ec..dd9ce4843 100644 --- a/discopop_library/discopop_optimizer/UpdateOptimization/RemoveLoopIndexUpdates.py +++ b/discopop_library/discopop_optimizer/UpdateOptimization/RemoveLoopIndexUpdates.py @@ -8,7 +8,7 @@ import logging from typing import List, Set, cast -from discopop_explorer.PEGraphX import LoopNode +from discopop_explorer.classes.LoopNode import LoopNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_library.discopop_optimizer.OptimizerArguments import OptimizerArguments from discopop_library.discopop_optimizer.Variables.Experiment import Experiment From bab42fb13b7cc12968c3d3db0e5a2bed263cfd3c Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 30 Jul 2024 17:20:57 +0200 Subject: [PATCH 058/105] refactor: utilities.PEGraphConstruction --- discopop_explorer/classes/FunctionNode.py | 4 +- discopop_explorer/classes/LoopNode.py | 2 +- discopop_explorer/classes/Node.py | 3 +- discopop_explorer/{ => classes}/PEGraphX.py | 157 ++---------------- discopop_explorer/discopop_explorer.py | 2 +- discopop_explorer/generate_Data_CUInst.py | 2 +- discopop_explorer/parallel_utils.py | 2 +- discopop_explorer/pattern_detection.py | 11 +- .../pattern_detectors/PatternInfo.py | 6 +- .../CombinedGPURegions.py | 2 +- .../classes/EntryPoint.py | 2 +- .../classes/ExitPoint.py | 2 +- .../combined_gpu_patterns/classes/Update.py | 2 +- .../combined_gpu_pattern_detector.py | 2 +- .../combined_gpu_patterns/prepare_metadata.py | 2 +- .../combined_gpu_patterns/step_1.py | 2 +- .../combined_gpu_patterns/step_2.py | 2 +- .../combined_gpu_patterns/step_3.py | 2 +- .../combined_gpu_patterns/step_4.py | 2 +- .../combined_gpu_patterns/step_5.py | 2 +- .../combined_gpu_patterns/step_6.py | 4 +- .../combined_gpu_patterns/utilities.py | 2 +- .../pattern_detectors/device_updates.py | 2 +- .../pattern_detectors/do_all_detector.py | 2 +- .../geometric_decomposition_detector.py | 2 +- .../pattern_detectors/pipeline_detector.py | 4 +- .../pattern_detectors/reduction_detector.py | 2 +- .../simple_gpu_patterns/GPULoop.py | 4 +- .../simple_gpu_patterns/GPUMemory.py | 2 +- .../simple_gpu_patterns/GPURegions.py | 2 +- .../gpu_pattern_detector.py | 2 +- .../task_parallelism/classes.py | 4 +- .../task_parallelism/filter.py | 4 +- .../task_parallelism/postprocessor.py | 2 +- .../task_parallelism/preprocessor.py | 3 +- .../task_parallelism/suggesters/auxiliary.py | 2 +- .../task_parallelism/suggesters/barriers.py | 2 +- .../suggesters/data_sharing_clauses.py | 2 +- .../suggesters/dependency_clauses.py | 2 +- .../task_parallelism/suggesters/tasks.py | 2 +- .../task_parallelism_detector.py | 3 +- .../task_parallelism/tp_utils.py | 3 +- discopop_explorer/plugins/pipeline.py | 2 +- .../utilities/PEGraphConstruction.py | 150 +++++++++++++++++ discopop_explorer/utilities/__init__.py | 0 discopop_explorer/utils.py | 2 +- .../PETParser/DataAccesses/FromCUs.py | 2 +- .../discopop_optimizer/PETParser/PETParser.py | 6 +- .../classes/context/Update.py | 3 +- .../classes/nodes/Workload.py | 3 +- .../gui/presentation/OptionTable.py | 14 +- .../result_classes/DetectionResult.py | 11 +- 52 files changed, 229 insertions(+), 232 deletions(-) rename discopop_explorer/{ => classes}/PEGraphX.py (90%) create mode 100644 discopop_explorer/utilities/PEGraphConstruction.py create mode 100644 discopop_explorer/utilities/__init__.py diff --git a/discopop_explorer/classes/FunctionNode.py b/discopop_explorer/classes/FunctionNode.py index c84c9dc4a..d6c2978f2 100644 --- a/discopop_explorer/classes/FunctionNode.py +++ b/discopop_explorer/classes/FunctionNode.py @@ -9,9 +9,9 @@ from typing import List, Optional, Dict, Set, cast, Tuple -import networkx as nx +import networkx as nx # type: ignore -from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.classes.CUNode import CUNode diff --git a/discopop_explorer/classes/LoopNode.py b/discopop_explorer/classes/LoopNode.py index 7f2347496..c97087394 100644 --- a/discopop_explorer/classes/LoopNode.py +++ b/discopop_explorer/classes/LoopNode.py @@ -9,7 +9,7 @@ from typing import Optional, List -from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.classes.FunctionNode import FunctionNode from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.classes.Node import Node diff --git a/discopop_explorer/classes/Node.py b/discopop_explorer/classes/Node.py index b1f4c0235..5d2e005fa 100644 --- a/discopop_explorer/classes/Node.py +++ b/discopop_explorer/classes/Node.py @@ -9,7 +9,8 @@ from typing import Optional, List, Dict, Any -from discopop_explorer.PEGraphX import parse_id, PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.utilities.PEGraphConstruction import parse_id from discopop_explorer.classes.FunctionNode import FunctionNode from discopop_explorer.aliases.LineID import LineID from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_explorer/PEGraphX.py b/discopop_explorer/classes/PEGraphX.py similarity index 90% rename from discopop_explorer/PEGraphX.py rename to discopop_explorer/classes/PEGraphX.py index a6d46afcc..d202ddc5b 100644 --- a/discopop_explorer/PEGraphX.py +++ b/discopop_explorer/classes/PEGraphX.py @@ -20,21 +20,22 @@ from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType from discopop_library.HostpotLoader.HotspotType import HotspotType # type:ignore -from .aliases.LineID import LineID -from .aliases.MemoryRegion import MemoryRegion -from .aliases.NodeID import NodeID -from .classes.CUNode import CUNode -from .classes.Dependency import Dependency -from .classes.DummyNode import DummyNode -from .classes.FunctionNode import FunctionNode -from .classes.LoopNode import LoopNode -from .classes.Node import Node -from .enums.DepType import DepType -from .enums.EdgeType import EdgeType -from .enums.NodeType import NodeType - -from .parser import LoopData, readlineToCUIdMap, writelineToCUIdMap, DependenceItem -from .variable import Variable +from discopop_explorer.aliases.LineID import LineID +from discopop_explorer.aliases.MemoryRegion import MemoryRegion +from discopop_explorer.aliases.NodeID import NodeID +from discopop_explorer.classes.CUNode import CUNode +from discopop_explorer.classes.Dependency import Dependency +from discopop_explorer.classes.DummyNode import DummyNode +from discopop_explorer.classes.FunctionNode import FunctionNode +from discopop_explorer.classes.LoopNode import LoopNode +from discopop_explorer.classes.Node import Node +from discopop_explorer.enums.DepType import DepType +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.enums.NodeType import NodeType + +from discopop_explorer.parser import LoopData, readlineToCUIdMap, writelineToCUIdMap, DependenceItem +from discopop_explorer.utilities.PEGraphConstruction import parse_dependency, parse_cu +from discopop_explorer.variable import Variable global_pet = None @@ -61,11 +62,6 @@ # ] -def parse_id(node_id: str) -> Tuple[int, int]: - split = node_id.split(":") - return int(split[0]), int(split[1]) - - # # check format of newly created MemoryRegion # try: # int(id_string) @@ -73,125 +69,6 @@ def parse_id(node_id: str) -> Tuple[int, int]: # raise ValueError("Mal-formatted MemoryRegion identifier: ", id_string) -def parse_cu(node: ObjectifiedElement) -> Node: - node_id = node.get("id") - node_type = NodeType(int(node.get("type"))) - - n: Node - # CU Node - if node_type == NodeType.CU: - n = CUNode(node_id) - if hasattr(node.localVariables, "local"): - n.local_vars = [ - Variable( - v.get("type"), - v.text, - v.get("defLine"), - v.get("accessMode"), - int(v.get("sizeInByte")) if v.get("sizeInByte") is not None else 0, - ) - for v in node.localVariables.local - ] - if hasattr(node.globalVariables, "global"): - n.global_vars = [ - Variable( - v.get("type"), - v.text, - v.get("defLine"), - v.get("accessMode"), - int(v.get("sizeInByte")) if v.get("sizeInByte") is not None else 0, - ) - for v in getattr(node.globalVariables, "global") - ] - if hasattr(node, "BasicBlockID"): - n.basic_block_id = getattr(node, "BasicBlockID").text - if hasattr(node, "returnInstructions"): - n.return_instructions_count = int(getattr(node, "returnInstructions").get("count")) - if hasattr(node.callsNode, "nodeCalled"): - n.node_calls = [ - {"cuid": v.text, "atLine": v.get("atLine")} - for v in getattr(node.callsNode, "nodeCalled") - if v.get("atLine") is not None - ] - if hasattr(node, "callsNode") and hasattr(node.callsNode, "recursiveFunctionCall"): - n.recursive_function_calls = [n.text for n in node.callsNode.recursiveFunctionCall] - if hasattr(node, "performsFileIO"): - n.performs_file_io = True if int(getattr(node, "performsFileIO")) == 1 else False - n.instructions_count = int(getattr(node, "instructionsCount")) - - # FUNC or DUMMY NODE - elif node_type == NodeType.DUMMY or node_type == NodeType.FUNC: - dummy_or_func: Union[DummyNode, FunctionNode] - if node_type == NodeType.DUMMY: - dummy_or_func = DummyNode(node_id) - else: - dummy_or_func = FunctionNode(node_id) - if hasattr(node, "funcArguments") and hasattr(node.funcArguments, "arg"): - dummy_or_func.args = [ - Variable( - v.get("type"), - v.text, - v.get("defLine"), - sizeInByte=int(v.get("sizeInByte")) if v.get("sizeInByte") is not None else 0, - ) - for v in node.funcArguments.arg - ] - n = dummy_or_func - - # LOOP Node - elif node_type == NodeType.LOOP: - n = LoopNode(node_id) - else: - assert False, "invalid NodeType" - - _, n.start_line = parse_id(node.get("startsAtLine")) - _, n.end_line = parse_id(node.get("endsAtLine")) - n.name = node.get("name") - - return n - - -def parse_dependency(dep: DependenceItem) -> Dependency: - d = Dependency(EdgeType.DATA) - d.source_line = dep.source - d.sink_line = dep.sink - # check for intra-iteration dependencies - if "_II_" in dep.type: - d.intra_iteration = True - # get intra_iteration_level - d.intra_iteration_level = int(dep.type[dep.type.rindex("_") + 1 :]) - d.dtype = DepType[dep.type[: dep.type.index("_")]] # remove _II_x tag - else: - d.dtype = DepType[dep.type] - d.var_name = dep.var_name - d.memory_region = dep.memory_region - # parse metadata - if len(dep.metadata) > 0: - for md in dep.metadata.split(" "): - if len(md) == 0: - continue - # unpack metadata - md_type = md[: md.index("[")] - md_raw_values = md[md.index("[") + 1 : -1] - md_values = [tmp for tmp in md_raw_values.split(",") if len(tmp) > 0] - # store metadata - if md_type == "IAI": - d.metadata_intra_iteration_dep += md_values - elif md_type == "IEI": - d.metadata_inter_iteration_dep += md_values - elif md_type == "IAC": - d.metadata_intra_call_dep += md_values - elif md_type == "IEC": - d.metadata_inter_call_dep += md_values - elif md_type == "SINK_ANC": - d.metadata_sink_ancestors += md_values - elif md_type == "SOURCE_ANC": - d.metadata_source_ancestors += md_values - else: - raise ValueError("Unknown metadata type: ", md_type) - return d - - class PEGraphX(object): g: nx.MultiDiGraph reduction_vars: List[Dict[str, str]] @@ -379,7 +256,7 @@ def calculateFunctionMetadata( print("Calculating local metadata results for functions...") import tqdm # type: ignore from multiprocessing import Pool - from .parallel_utils import pet_function_metadata_initialize_worker, pet_function_metadata_parse_func + from ..parallel_utils import pet_function_metadata_initialize_worker, pet_function_metadata_parse_func param_list = func_nodes with Pool(initializer=pet_function_metadata_initialize_worker, initargs=(self,)) as pool: diff --git a/discopop_explorer/discopop_explorer.py b/discopop_explorer/discopop_explorer.py index 27bbdc177..c03419db5 100644 --- a/discopop_explorer/discopop_explorer.py +++ b/discopop_explorer/discopop_explorer.py @@ -29,7 +29,7 @@ ExtrapInterpolatedMicrobench, ) from discopop_library.result_classes.DetectionResult import DetectionResult -from .PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from .json_serializer import PatternBaseSerializer from .parser import parse_inputs from .pattern_detection import PatternDetectorX diff --git a/discopop_explorer/generate_Data_CUInst.py b/discopop_explorer/generate_Data_CUInst.py index 3a936aee9..c42eba4d3 100644 --- a/discopop_explorer/generate_Data_CUInst.py +++ b/discopop_explorer/generate_Data_CUInst.py @@ -9,7 +9,7 @@ from io import TextIOWrapper from typing import List, cast, TextIO -from .PEGraphX import ( +from discopop_explorer.classes.PEGraphX import ( PEGraphX, ) from .classes.FunctionNode import FunctionNode diff --git a/discopop_explorer/parallel_utils.py b/discopop_explorer/parallel_utils.py index ab709f818..a49107ecf 100644 --- a/discopop_explorer/parallel_utils.py +++ b/discopop_explorer/parallel_utils.py @@ -6,7 +6,7 @@ # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. -from .PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from .classes.FunctionNode import FunctionNode from .classes.Node import Node from .aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detection.py b/discopop_explorer/pattern_detection.py index da6e750c3..1230eef5b 100644 --- a/discopop_explorer/pattern_detection.py +++ b/discopop_explorer/pattern_detection.py @@ -7,7 +7,6 @@ # directory for details. import json import os -import sys from typing import Dict, List, Optional, Tuple, cast from alive_progress import alive_bar # type: ignore @@ -20,18 +19,10 @@ from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType from discopop_library.HostpotLoader.HotspotType import HotspotType from discopop_library.JSONHandler.JSONHandler import read_patterns_from_json_to_json -from discopop_library.discopop_optimizer.OptimizationGraph import OptimizationGraph -from discopop_library.discopop_optimizer.Variables.Experiment import Experiment -from discopop_library.discopop_optimizer.classes.system.System import System -from discopop_library.discopop_optimizer.scheduling.workload_delta import ( - get_workload_delta_for_cu_node, -) -from discopop_library.discopop_optimizer.utilities.MOGUtilities import get_nodes_from_cu_id from discopop_library.result_classes.DetectionResult import DetectionResult -from .PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from .classes.DummyNode import DummyNode from .classes.LoopNode import LoopNode -from .aliases.NodeID import NodeID from .enums.EdgeType import EdgeType from .pattern_detectors.do_all_detector import DoAllInfo, run_detection as detect_do_all from .pattern_detectors.geometric_decomposition_detector import run_detection as detect_gd diff --git a/discopop_explorer/pattern_detectors/PatternInfo.py b/discopop_explorer/pattern_detectors/PatternInfo.py index dda9d7902..f41e3daef 100644 --- a/discopop_explorer/pattern_detectors/PatternInfo.py +++ b/discopop_explorer/pattern_detectors/PatternInfo.py @@ -5,18 +5,14 @@ # This software may be modified and distributed under the terms of # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. -import json -import os from typing import Optional from discopop_explorer.pattern_detectors.PatternBase import PatternBase from discopop_library.discopop_optimizer.classes.system.devices.DeviceTypeEnum import DeviceTypeEnum -from ..PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from ..classes.LoopNode import LoopNode from ..classes.Node import Node -from ..aliases.LineID import LineID -from ..aliases.NodeID import NodeID from ..utils import calculate_workload, calculate_per_iteration_workload_of_loop diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py index ba7a39471..754d8bfcb 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py @@ -8,7 +8,7 @@ import sys from typing import List, Tuple, Dict, Set, cast -from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py index d5373146b..8bd8b7b11 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py @@ -8,7 +8,7 @@ import os.path from typing import Set, Tuple, List -from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py index bdedf57c4..0d0c69a34 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py @@ -9,7 +9,7 @@ import os from typing import Set, List, Tuple -from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py index f09673a52..3f29a1c85 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py @@ -9,7 +9,7 @@ import os from typing import Set, Dict, cast, Optional, List, Tuple -from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.LineID import LineID from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/combined_gpu_pattern_detector.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/combined_gpu_pattern_detector.py index 0137c5140..7a9e58035 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/combined_gpu_pattern_detector.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/combined_gpu_pattern_detector.py @@ -8,7 +8,7 @@ from typing import List, cast -from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.combined_gpu_patterns.CombinedGPURegions import ( find_combined_gpu_regions, diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/prepare_metadata.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/prepare_metadata.py index 14d11d006..65dee6804 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/prepare_metadata.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/prepare_metadata.py @@ -8,7 +8,7 @@ from typing import Set, List, Tuple -from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import VarName from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Dependency import Dependency diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py index e83a482cb..224925315 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py @@ -8,7 +8,7 @@ from typing import List, Tuple, Dict, Set, cast -from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py index 3671e3ed9..55da7b6df 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py @@ -11,7 +11,7 @@ import networkx as nx # type: ignore -from discopop_explorer.PEGraphX import ( +from discopop_explorer.classes.PEGraphX import ( PEGraphX, ) from discopop_explorer.classes.FunctionNode import FunctionNode diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py index a67969b5e..e5bead1e1 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py @@ -8,7 +8,7 @@ from typing import Dict, List, Tuple, Set, Optional -from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py index f24e2689f..f39c259c8 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py @@ -13,7 +13,7 @@ import networkx as nx # type: ignore from networkx import NetworkXNoCycle, MultiDiGraph -from discopop_explorer.PEGraphX import ( +from discopop_explorer.classes.PEGraphX import ( PEGraphX, ) from discopop_explorer.classes.FunctionNode import FunctionNode diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_5.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_5.py index d2409a9bc..21a9f7656 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_5.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_5.py @@ -8,7 +8,7 @@ from typing import Dict, Set -from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py index 5fb50ba6b..d388e2509 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py @@ -7,11 +7,11 @@ # directory for details. import copy import sys -from typing import Any, Set, Tuple, Dict, List, TypeVar, cast, Optional, Union, overload +from typing import Any, Set, Tuple, Dict, List, cast, Union from networkx import MultiDiGraph # type: ignore -from discopop_explorer.PEGraphX import ( +from discopop_explorer.classes.PEGraphX import ( PEGraphX, ) from discopop_explorer.classes.FunctionNode import FunctionNode diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py index 80f69fec6..ff9a76c82 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py @@ -8,7 +8,7 @@ from typing import List, Set, Dict, Tuple, Optional -from discopop_explorer.PEGraphX import ( +from discopop_explorer.classes.PEGraphX import ( PEGraphX, ) from discopop_explorer.classes.FunctionNode import FunctionNode diff --git a/discopop_explorer/pattern_detectors/device_updates.py b/discopop_explorer/pattern_detectors/device_updates.py index 4ec55c791..ac448c6be 100644 --- a/discopop_explorer/pattern_detectors/device_updates.py +++ b/discopop_explorer/pattern_detectors/device_updates.py @@ -8,7 +8,7 @@ from typing import Optional from .PatternInfo import PatternInfo -from ..PEGraphX import ( +from discopop_explorer.classes.PEGraphX import ( PEGraphX, ) from ..classes.Node import Node diff --git a/discopop_explorer/pattern_detectors/do_all_detector.py b/discopop_explorer/pattern_detectors/do_all_detector.py index 5d02db75e..e853f8522 100644 --- a/discopop_explorer/pattern_detectors/do_all_detector.py +++ b/discopop_explorer/pattern_detectors/do_all_detector.py @@ -15,7 +15,7 @@ from .PatternInfo import PatternInfo from .reduction_detector import ReductionInfo -from ..PEGraphX import ( +from discopop_explorer.classes.PEGraphX import ( PEGraphX, ) from ..classes.LoopNode import LoopNode diff --git a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py index 6a5480efb..52fb1577f 100644 --- a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py +++ b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py @@ -15,7 +15,7 @@ from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore from .PatternInfo import PatternInfo -from ..PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from ..classes.FunctionNode import FunctionNode from ..classes.LoopNode import LoopNode from ..classes.Node import Node diff --git a/discopop_explorer/pattern_detectors/pipeline_detector.py b/discopop_explorer/pattern_detectors/pipeline_detector.py index 809275923..444462847 100644 --- a/discopop_explorer/pattern_detectors/pipeline_detector.py +++ b/discopop_explorer/pattern_detectors/pipeline_detector.py @@ -7,13 +7,13 @@ # directory for details. -from typing import List, Optional, Tuple, Dict, Set, cast +from typing import List, Optional, Tuple, Dict, cast from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore from .PatternInfo import PatternInfo -from ..PEGraphX import ( +from discopop_explorer.classes.PEGraphX import ( PEGraphX, ) from ..classes.LoopNode import LoopNode diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index 307973669..0ab675915 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -15,7 +15,7 @@ from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore from .PatternInfo import PatternInfo -from ..PEGraphX import ( +from discopop_explorer.classes.PEGraphX import ( PEGraphX, ) from ..classes.LoopNode import LoopNode diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py index 0fe6909e3..3e54a0f18 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py @@ -9,10 +9,10 @@ from enum import IntEnum from typing import List, Set, Optional, Union, Any, Dict, Tuple, cast -from discopop_explorer.PEGraphX import ( +from discopop_explorer.classes.PEGraphX import ( PEGraphX, - parse_id, ) +from ...utilities.PEGraphConstruction import parse_id from ...classes.FunctionNode import FunctionNode from ...classes.LoopNode import LoopNode from ...classes.CUNode import CUNode diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py index cce7ee88b..dca871d70 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py @@ -9,7 +9,7 @@ from enum import Enum from typing import List, Set, cast, Tuple -from discopop_explorer.PEGraphX import ( +from discopop_explorer.classes.PEGraphX import ( PEGraphX, ) from discopop_explorer.classes.FunctionNode import FunctionNode diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py index adfdccd92..1fc9b6578 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py @@ -10,7 +10,7 @@ from alive_progress import alive_bar # type: ignore -from discopop_explorer.PEGraphX import ( +from discopop_explorer.classes.PEGraphX import ( PEGraphX, ) from ...classes.LoopNode import LoopNode diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py index ace093359..be9e422aa 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py @@ -10,7 +10,7 @@ from alive_progress import alive_bar # type: ignore -from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.classes.LoopNode import LoopNode from discopop_explorer.aliases.LineID import LineID from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo diff --git a/discopop_explorer/pattern_detectors/task_parallelism/classes.py b/discopop_explorer/pattern_detectors/task_parallelism/classes.py index 7d87e4e8c..2db546b61 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/classes.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/classes.py @@ -9,7 +9,7 @@ from enum import Enum from typing import List, Optional -from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.classes.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.MWType import MWType @@ -17,7 +17,7 @@ # We decided to omit the information that computes the workload and the relevant codes. For large programs (e.g., ffmpeg), the generated Data.xml file becomes very large. However, we keep the code here because we would like to integrate a hotspot detection algorithm (TODO: Bertin) with the parallelism discovery. Then, we need to retrieve the information to decide which code sections (loops or functions) are worth parallelizing. -# from discopop_explorer.utils import total_instructions_count, calculate_workload +# from discopop_explorer.utilities import total_instructions_count, calculate_workload class Task(object): diff --git a/discopop_explorer/pattern_detectors/task_parallelism/filter.py b/discopop_explorer/pattern_detectors/task_parallelism/filter.py index 3ac38c0d7..1d9e7a4ca 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/filter.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/filter.py @@ -8,10 +8,9 @@ from typing import List, Dict, cast, Optional, Union -from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.classes.Node import Node -from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo @@ -27,7 +26,6 @@ check_reachability, ) from discopop_explorer.utils import is_loop_index2 -from discopop_library.discopop_optimizer.classes.nodes.FunctionRoot import FunctionRoot def filter_data_sharing_clauses( diff --git a/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py b/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py index 72f86f013..f938fce6b 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py @@ -8,7 +8,7 @@ from typing import List, cast, Dict, Optional, Tuple -from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.classes.Node import Node from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo diff --git a/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py b/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py index 8449f9c39..12588a149 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py @@ -12,8 +12,7 @@ from lxml import objectify, etree # type: ignore -import discopop_explorer.classes.Node -from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.classes.LoopNode import LoopNode from discopop_explorer.pattern_detectors.task_parallelism.tp_utils import line_contained_in_region diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py index 5ce0ccf21..801b96f51 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py @@ -9,7 +9,7 @@ import copy from typing import List, Tuple, Optional, cast, Dict -from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.classes.Node import Node from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py index db4cc5f6a..d3f676184 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py @@ -8,7 +8,7 @@ from typing import List, cast, Tuple, Any -from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.classes.Node import Node from discopop_explorer.aliases.LineID import LineID diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py index b33243cd3..aa15bf150 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py @@ -8,7 +8,7 @@ from typing import List -from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.classes.FunctionNode import FunctionNode from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py index 118287085..7be11dfbf 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py @@ -9,7 +9,7 @@ import os from typing import List, Dict, Tuple, Optional, cast, Any -from discopop_explorer.PEGraphX import ( +from discopop_explorer.classes.PEGraphX import ( PEGraphX, ) from discopop_explorer.classes.FunctionNode import FunctionNode diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py index ffd60725c..3b2e75d04 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py @@ -8,7 +8,7 @@ from typing import List, Dict, cast -from discopop_explorer.PEGraphX import ( +from discopop_explorer.classes.PEGraphX import ( PEGraphX, ) from discopop_explorer.classes.FunctionNode import FunctionNode diff --git a/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py b/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py index 48e6da52d..ee46fc17c 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py @@ -9,7 +9,7 @@ from typing import Dict, List, Optional, Tuple, cast -from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.classes.DummyNode import DummyNode from discopop_explorer.enums.MWType import MWType from discopop_explorer.parser import parse_inputs @@ -17,7 +17,6 @@ from discopop_explorer.pattern_detectors.do_all_detector import run_detection as detect_do_all from discopop_explorer.pattern_detectors.reduction_detector import ReductionInfo, run_detection as detect_reduction from discopop_explorer.pattern_detectors.task_parallelism.classes import ( - Task, TaskParallelismInfo, TPIType, ) diff --git a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py index 66c8c5466..9e8d2f007 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py @@ -11,8 +11,7 @@ from lxml import objectify # type: ignore -import discopop_explorer.classes.Node -from discopop_explorer.PEGraphX import ( +from discopop_explorer.classes.PEGraphX import ( PEGraphX, ) from discopop_explorer.classes.FunctionNode import FunctionNode diff --git a/discopop_explorer/plugins/pipeline.py b/discopop_explorer/plugins/pipeline.py index 04eca0899..cda66a644 100644 --- a/discopop_explorer/plugins/pipeline.py +++ b/discopop_explorer/plugins/pipeline.py @@ -9,7 +9,7 @@ from copy import deepcopy from typing import List -from ..PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from ..classes.LoopNode import LoopNode from ..classes.Node import Node from ..aliases.LineID import LineID diff --git a/discopop_explorer/utilities/PEGraphConstruction.py b/discopop_explorer/utilities/PEGraphConstruction.py new file mode 100644 index 000000000..528d3d63e --- /dev/null +++ b/discopop_explorer/utilities/PEGraphConstruction.py @@ -0,0 +1,150 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from __future__ import annotations + +from typing import Union, Tuple + +from lxml.objectify import ObjectifiedElement # type: ignore + +from discopop_explorer.classes.CUNode import CUNode + +from discopop_explorer.classes.Dependency import Dependency +from discopop_explorer.classes.DummyNode import DummyNode +from discopop_explorer.classes.FunctionNode import FunctionNode +from discopop_explorer.classes.LoopNode import LoopNode +from discopop_explorer.classes.Node import Node +from discopop_explorer.enums.DepType import DepType +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.enums.NodeType import NodeType +from discopop_explorer.parser import DependenceItem +from discopop_explorer.variable import Variable + + +def parse_dependency(dep: DependenceItem) -> Dependency: + d = Dependency(EdgeType.DATA) + d.source_line = dep.source + d.sink_line = dep.sink + # check for intra-iteration dependencies + if "_II_" in dep.type: + d.intra_iteration = True + # get intra_iteration_level + d.intra_iteration_level = int(dep.type[dep.type.rindex("_") + 1 :]) + d.dtype = DepType[dep.type[: dep.type.index("_")]] # remove _II_x tag + else: + d.dtype = DepType[dep.type] + d.var_name = dep.var_name + d.memory_region = dep.memory_region + # parse metadata + if len(dep.metadata) > 0: + for md in dep.metadata.split(" "): + if len(md) == 0: + continue + # unpack metadata + md_type = md[: md.index("[")] + md_raw_values = md[md.index("[") + 1 : -1] + md_values = [tmp for tmp in md_raw_values.split(",") if len(tmp) > 0] + # store metadata + if md_type == "IAI": + d.metadata_intra_iteration_dep += md_values + elif md_type == "IEI": + d.metadata_inter_iteration_dep += md_values + elif md_type == "IAC": + d.metadata_intra_call_dep += md_values + elif md_type == "IEC": + d.metadata_inter_call_dep += md_values + elif md_type == "SINK_ANC": + d.metadata_sink_ancestors += md_values + elif md_type == "SOURCE_ANC": + d.metadata_source_ancestors += md_values + else: + raise ValueError("Unknown metadata type: ", md_type) + return d + + +def parse_cu(node: ObjectifiedElement) -> Node: + node_id = node.get("id") + node_type = NodeType(int(node.get("type"))) + + n: Node + # CU Node + if node_type == NodeType.CU: + n = CUNode(node_id) + if hasattr(node.localVariables, "local"): + n.local_vars = [ + Variable( + v.get("type"), + v.text, + v.get("defLine"), + v.get("accessMode"), + int(v.get("sizeInByte")) if v.get("sizeInByte") is not None else 0, + ) + for v in node.localVariables.local + ] + if hasattr(node.globalVariables, "global"): + n.global_vars = [ + Variable( + v.get("type"), + v.text, + v.get("defLine"), + v.get("accessMode"), + int(v.get("sizeInByte")) if v.get("sizeInByte") is not None else 0, + ) + for v in getattr(node.globalVariables, "global") + ] + if hasattr(node, "BasicBlockID"): + n.basic_block_id = getattr(node, "BasicBlockID").text + if hasattr(node, "returnInstructions"): + n.return_instructions_count = int(getattr(node, "returnInstructions").get("count")) + if hasattr(node.callsNode, "nodeCalled"): + n.node_calls = [ + {"cuid": v.text, "atLine": v.get("atLine")} + for v in getattr(node.callsNode, "nodeCalled") + if v.get("atLine") is not None + ] + if hasattr(node, "callsNode") and hasattr(node.callsNode, "recursiveFunctionCall"): + n.recursive_function_calls = [n.text for n in node.callsNode.recursiveFunctionCall] + if hasattr(node, "performsFileIO"): + n.performs_file_io = True if int(getattr(node, "performsFileIO")) == 1 else False + n.instructions_count = int(getattr(node, "instructionsCount")) + + # FUNC or DUMMY NODE + elif node_type == NodeType.DUMMY or node_type == NodeType.FUNC: + dummy_or_func: Union[DummyNode, FunctionNode] + if node_type == NodeType.DUMMY: + dummy_or_func = DummyNode(node_id) + else: + dummy_or_func = FunctionNode(node_id) + if hasattr(node, "funcArguments") and hasattr(node.funcArguments, "arg"): + dummy_or_func.args = [ + Variable( + v.get("type"), + v.text, + v.get("defLine"), + sizeInByte=int(v.get("sizeInByte")) if v.get("sizeInByte") is not None else 0, + ) + for v in node.funcArguments.arg + ] + n = dummy_or_func + + # LOOP Node + elif node_type == NodeType.LOOP: + n = LoopNode(node_id) + else: + assert False, "invalid NodeType" + + _, n.start_line = parse_id(node.get("startsAtLine")) + _, n.end_line = parse_id(node.get("endsAtLine")) + n.name = node.get("name") + + return n + + +def parse_id(node_id: str) -> Tuple[int, int]: + split = node_id.split(":") + return int(split[0]), int(split[1]) diff --git a/discopop_explorer/utilities/__init__.py b/discopop_explorer/utilities/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index 2c9288d06..06b8ae9e6 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -14,7 +14,7 @@ from discopop_library.HostpotLoader.HotspotType import HotspotType -from .PEGraphX import ( +from discopop_explorer.classes.PEGraphX import ( PEGraphX, ) from .classes.FunctionNode import FunctionNode diff --git a/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py b/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py index 767118488..31574f1b6 100644 --- a/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py +++ b/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py @@ -7,7 +7,7 @@ # directory for details. from typing import Tuple, Set, cast -from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_library/discopop_optimizer/PETParser/PETParser.py b/discopop_library/discopop_optimizer/PETParser/PETParser.py index 15757804c..c8fdc91f8 100644 --- a/discopop_library/discopop_optimizer/PETParser/PETParser.py +++ b/discopop_library/discopop_optimizer/PETParser/PETParser.py @@ -16,7 +16,7 @@ from sympy import Integer -from discopop_explorer.PEGraphX import ( +from discopop_explorer.classes.PEGraphX import ( PEGraphX, ) from discopop_explorer.classes.FunctionNode import FunctionNode @@ -39,7 +39,6 @@ from discopop_library.discopop_optimizer.classes.nodes.ContextSnapshotPop import ContextSnapshotPop from discopop_library.discopop_optimizer.classes.nodes.FunctionReturn import FunctionReturn from discopop_library.discopop_optimizer.classes.nodes.FunctionRoot import FunctionRoot -from discopop_library.discopop_optimizer.classes.nodes.GenericNode import GenericNode from discopop_library.discopop_optimizer.classes.nodes.Loop import Loop from discopop_library.discopop_optimizer.classes.nodes.Workload import Workload from discopop_library.discopop_optimizer.classes.types.DataAccessType import ReadDataAccess, WriteDataAccess @@ -50,8 +49,6 @@ get_all_parents, get_nodes_by_functions, get_out_call_edges, - get_parent_function, - get_parents, get_path_entry, get_predecessors, get_successors, @@ -64,7 +61,6 @@ get_all_function_nodes, get_read_and_written_data_from_subgraph, remove_edge, - show, show_function, ) from discopop_library.discopop_optimizer.utilities.simple_utilities import data_at diff --git a/discopop_library/discopop_optimizer/classes/context/Update.py b/discopop_library/discopop_optimizer/classes/context/Update.py index fc29090cc..186caf6ee 100644 --- a/discopop_library/discopop_optimizer/classes/context/Update.py +++ b/discopop_library/discopop_optimizer/classes/context/Update.py @@ -7,11 +7,10 @@ # directory for details. import json from typing import Any, Dict, Optional, Tuple, cast -from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.aliases.NodeID import NodeID from discopop_library.discopop_optimizer.classes.types.Aliases import DeviceID from discopop_library.discopop_optimizer.classes.types.DataAccessType import ( - ReadDataAccess, WriteDataAccess, write_data_access_from_dict, ) diff --git a/discopop_library/discopop_optimizer/classes/nodes/Workload.py b/discopop_library/discopop_optimizer/classes/nodes/Workload.py index f42e96e4b..22b1dc207 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/Workload.py +++ b/discopop_library/discopop_optimizer/classes/nodes/Workload.py @@ -6,11 +6,10 @@ # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. from __future__ import annotations -from typing import Optional, Set, List, cast +from typing import Optional, Set, List from sympy import Integer, Expr # type: ignore -from discopop_explorer.PEGraphX import PEGraphX from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel diff --git a/discopop_library/discopop_optimizer/gui/presentation/OptionTable.py b/discopop_library/discopop_optimizer/gui/presentation/OptionTable.py index e0e544cad..f0fc34c9a 100644 --- a/discopop_library/discopop_optimizer/gui/presentation/OptionTable.py +++ b/discopop_library/discopop_optimizer/gui/presentation/OptionTable.py @@ -12,7 +12,7 @@ import networkx as nx # type: ignore from sympy import Symbol -from discopop_explorer.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.context.ContextObject import ContextObject @@ -212,12 +212,12 @@ def show_options( def __update_selection(cm: CostModel, ctx: ContextObject) -> None: experiment.selected_paths_per_function[function_root] = (cm, ctx) - experiment.substitutions[cast(Symbol, function_root.sequential_costs)] = ( - experiment.selected_paths_per_function[function_root][0].sequential_costs - ) - experiment.substitutions[cast(Symbol, function_root.parallelizable_costs)] = ( - experiment.selected_paths_per_function[function_root][0].parallelizable_costs - ) + experiment.substitutions[ + cast(Symbol, function_root.sequential_costs) + ] = experiment.selected_paths_per_function[function_root][0].sequential_costs + experiment.substitutions[ + cast(Symbol, function_root.parallelizable_costs) + ] = experiment.selected_paths_per_function[function_root][0].parallelizable_costs # update displayed value label2.configure(state=NORMAL) label2.delete(0, END) diff --git a/discopop_library/result_classes/DetectionResult.py b/discopop_library/result_classes/DetectionResult.py index ac8f13bc4..efa39fe0b 100644 --- a/discopop_library/result_classes/DetectionResult.py +++ b/discopop_library/result_classes/DetectionResult.py @@ -5,18 +5,11 @@ # This software may be modified and distributed under the terms of # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. -from ast import Dict -from typing import List, cast +from typing import cast import jsonpickle # type: ignore -from discopop_explorer.PEGraphX import PEGraphX -from discopop_explorer.pattern_detectors.PatternBase import PatternBase -from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo -from discopop_explorer.pattern_detectors.do_all_detector import DoAllInfo -from discopop_explorer.pattern_detectors.geometric_decomposition_detector import GDInfo -from discopop_explorer.pattern_detectors.pipeline_detector import PipelineInfo -from discopop_explorer.pattern_detectors.reduction_detector import ReductionInfo +from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_library.global_data.version.utils import get_version from discopop_library.result_classes.PatternStorage import PatternStorage From 81e35735645ea229c1cde0c1ae53b99732544e08 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 31 Jul 2024 10:03:22 +0200 Subject: [PATCH 059/105] refactor: PatternInfo --- .../{pattern_detectors => classes/patterns}/PatternInfo.py | 6 +++--- discopop_explorer/classes/patterns/__init__.py | 0 discopop_explorer/json_serializer.py | 3 +-- .../combined_gpu_patterns/CombinedGPURegions.py | 2 +- .../combined_gpu_patterns/combined_gpu_pattern_detector.py | 2 +- discopop_explorer/pattern_detectors/device_updates.py | 2 +- discopop_explorer/pattern_detectors/do_all_detector.py | 2 +- .../pattern_detectors/geometric_decomposition_detector.py | 2 +- discopop_explorer/pattern_detectors/pipeline_detector.py | 2 +- discopop_explorer/pattern_detectors/reduction_detector.py | 2 +- .../pattern_detectors/simple_gpu_patterns/GPULoop.py | 2 +- .../pattern_detectors/simple_gpu_patterns/GPURegions.py | 2 +- .../simple_gpu_patterns/gpu_pattern_detector.py | 2 +- .../pattern_detectors/task_parallelism/classes.py | 2 +- .../pattern_detectors/task_parallelism/filter.py | 2 +- .../pattern_detectors/task_parallelism/postprocessor.py | 2 +- .../task_parallelism/suggesters/auxiliary.py | 2 +- .../task_parallelism/suggesters/barriers.py | 2 +- .../task_parallelism/suggesters/data_sharing_clauses.py | 2 +- .../task_parallelism/suggesters/dependency_clauses.py | 2 +- .../pattern_detectors/task_parallelism/suggesters/tasks.py | 2 +- .../task_parallelism/task_parallelism_detector.py | 2 +- discopop_library/CodeGenerator/CodeGenerator.py | 2 +- .../discopop_optimizer/classes/nodes/GenericNode.py | 2 +- .../discopop_optimizer/classes/system/devices/Device.py | 2 +- .../discopop_optimizer/classes/system/devices/GPU.py | 2 +- discopop_library/result_classes/PatternStorage.py | 2 +- 27 files changed, 28 insertions(+), 29 deletions(-) rename discopop_explorer/{pattern_detectors => classes/patterns}/PatternInfo.py (93%) create mode 100644 discopop_explorer/classes/patterns/__init__.py diff --git a/discopop_explorer/pattern_detectors/PatternInfo.py b/discopop_explorer/classes/patterns/PatternInfo.py similarity index 93% rename from discopop_explorer/pattern_detectors/PatternInfo.py rename to discopop_explorer/classes/patterns/PatternInfo.py index f41e3daef..e8db06ee2 100644 --- a/discopop_explorer/pattern_detectors/PatternInfo.py +++ b/discopop_explorer/classes/patterns/PatternInfo.py @@ -11,9 +11,9 @@ from discopop_library.discopop_optimizer.classes.system.devices.DeviceTypeEnum import DeviceTypeEnum from discopop_explorer.classes.PEGraphX import PEGraphX -from ..classes.LoopNode import LoopNode -from ..classes.Node import Node -from ..utils import calculate_workload, calculate_per_iteration_workload_of_loop +from discopop_explorer.classes.LoopNode import LoopNode +from discopop_explorer.classes.Node import Node +from discopop_explorer.utils import calculate_workload, calculate_per_iteration_workload_of_loop class PatternInfo(PatternBase): diff --git a/discopop_explorer/classes/patterns/__init__.py b/discopop_explorer/classes/patterns/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/discopop_explorer/json_serializer.py b/discopop_explorer/json_serializer.py index 56d7a10ae..35579efc6 100644 --- a/discopop_explorer/json_serializer.py +++ b/discopop_explorer/json_serializer.py @@ -7,7 +7,7 @@ # directory for details. from json import JSONEncoder -from typing import Dict, Any, List +from typing import Dict, Any from discopop_explorer.pattern_detectors.PatternBase import PatternBase from discopop_library.discopop_optimizer.classes.context.Update import Update from discopop_library.discopop_optimizer.classes.types.DataAccessType import WriteDataAccess @@ -15,7 +15,6 @@ from discopop_library.result_classes.DetectionResult import DetectionResult from discopop_library.result_classes.PatternStorage import PatternStorage from .classes.Node import Node -from .pattern_detectors.PatternInfo import PatternInfo from .pattern_detectors.pipeline_detector import PipelineStage from .pattern_detectors.task_parallelism.classes import TPIType from .variable import Variable diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py index 754d8bfcb..98749b506 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py @@ -13,7 +13,7 @@ from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType -from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo +from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, ) diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/combined_gpu_pattern_detector.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/combined_gpu_pattern_detector.py index 7a9e58035..842a3c12b 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/combined_gpu_pattern_detector.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/combined_gpu_pattern_detector.py @@ -9,7 +9,7 @@ from typing import List, cast from discopop_explorer.classes.PEGraphX import PEGraphX -from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo +from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.combined_gpu_patterns.CombinedGPURegions import ( find_combined_gpu_regions, ) diff --git a/discopop_explorer/pattern_detectors/device_updates.py b/discopop_explorer/pattern_detectors/device_updates.py index ac448c6be..5d84caaad 100644 --- a/discopop_explorer/pattern_detectors/device_updates.py +++ b/discopop_explorer/pattern_detectors/device_updates.py @@ -7,7 +7,7 @@ # directory for details. from typing import Optional -from .PatternInfo import PatternInfo +from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.classes.PEGraphX import ( PEGraphX, ) diff --git a/discopop_explorer/pattern_detectors/do_all_detector.py b/discopop_explorer/pattern_detectors/do_all_detector.py index e853f8522..fc0b79442 100644 --- a/discopop_explorer/pattern_detectors/do_all_detector.py +++ b/discopop_explorer/pattern_detectors/do_all_detector.py @@ -13,7 +13,7 @@ from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore -from .PatternInfo import PatternInfo +from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from .reduction_detector import ReductionInfo from discopop_explorer.classes.PEGraphX import ( PEGraphX, diff --git a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py index 52fb1577f..fd62243f8 100644 --- a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py +++ b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py @@ -14,7 +14,7 @@ from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore -from .PatternInfo import PatternInfo +from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.classes.PEGraphX import PEGraphX from ..classes.FunctionNode import FunctionNode from ..classes.LoopNode import LoopNode diff --git a/discopop_explorer/pattern_detectors/pipeline_detector.py b/discopop_explorer/pattern_detectors/pipeline_detector.py index 444462847..42161f0a4 100644 --- a/discopop_explorer/pattern_detectors/pipeline_detector.py +++ b/discopop_explorer/pattern_detectors/pipeline_detector.py @@ -12,7 +12,7 @@ from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore -from .PatternInfo import PatternInfo +from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.classes.PEGraphX import ( PEGraphX, ) diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index 0ab675915..8dbb19280 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -14,7 +14,7 @@ from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore -from .PatternInfo import PatternInfo +from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.classes.PEGraphX import ( PEGraphX, ) diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py index 3e54a0f18..556ff66e0 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py @@ -21,7 +21,7 @@ from ...aliases.LineID import LineID from ...aliases.NodeID import NodeID from ...enums.DepType import DepType -from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo +from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.utils import ( __get_dep_of_type as get_dep_of_type, ) diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py index 1fc9b6578..d800a3b86 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py @@ -23,7 +23,7 @@ from discopop_explorer.variable import Variable from .GPULoop import GPULoopPattern from .GPUMemory import map_node -from ..PatternInfo import PatternInfo +from discopop_explorer.classes.patterns.PatternInfo import PatternInfo class GPURegionInfo(PatternInfo): diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py index be9e422aa..a3a3bfac3 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py @@ -13,7 +13,7 @@ from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.classes.LoopNode import LoopNode from discopop_explorer.aliases.LineID import LineID -from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo +from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.simple_gpu_patterns.GPULoop import GPULoopPattern from discopop_explorer.pattern_detectors.simple_gpu_patterns.GPURegions import ( GPURegions, diff --git a/discopop_explorer/pattern_detectors/task_parallelism/classes.py b/discopop_explorer/pattern_detectors/task_parallelism/classes.py index 2db546b61..c7480002d 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/classes.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/classes.py @@ -13,7 +13,7 @@ from discopop_explorer.classes.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.MWType import MWType -from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo +from discopop_explorer.classes.patterns.PatternInfo import PatternInfo # We decided to omit the information that computes the workload and the relevant codes. For large programs (e.g., ffmpeg), the generated Data.xml file becomes very large. However, we keep the code here because we would like to integrate a hotspot detection algorithm (TODO: Bertin) with the parallelism discovery. Then, we need to retrieve the information to decide which code sections (loops or functions) are worth parallelizing. diff --git a/discopop_explorer/pattern_detectors/task_parallelism/filter.py b/discopop_explorer/pattern_detectors/task_parallelism/filter.py index 1d9e7a4ca..31f8c89e8 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/filter.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/filter.py @@ -13,7 +13,7 @@ from discopop_explorer.classes.Node import Node from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType -from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo +from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.task_parallelism.classes import ( TaskParallelismInfo, ParallelRegionInfo, diff --git a/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py b/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py index f938fce6b..9d6d84a6a 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py @@ -11,7 +11,7 @@ from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.classes.Node import Node from discopop_explorer.enums.EdgeType import EdgeType -from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo +from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.task_parallelism.classes import ( TaskParallelismInfo, ParallelRegionInfo, diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py index 801b96f51..731a35347 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py @@ -13,7 +13,7 @@ from discopop_explorer.classes.Node import Node from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType -from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo +from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.task_parallelism.classes import ( TaskParallelismInfo, ParallelRegionInfo, diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py index d3f676184..4eeb80442 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py @@ -14,7 +14,7 @@ from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType -from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo +from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.task_parallelism.classes import ( ParallelRegionInfo, OmittableCuInfo, diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py index aa15bf150..32debfdaf 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py @@ -11,7 +11,7 @@ from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.classes.FunctionNode import FunctionNode from discopop_explorer.enums.EdgeType import EdgeType -from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo +from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.task_parallelism.classes import ( TaskParallelismInfo, TPIType, diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py index 7be11dfbf..efb085312 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py @@ -18,7 +18,7 @@ from discopop_explorer.aliases.LineID import LineID from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType -from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo +from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import VarName from discopop_explorer.pattern_detectors.task_parallelism.alias_detection import ( get_alias_information as get_alias_detection_result, diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py index 3b2e75d04..c1919b2a9 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py @@ -18,7 +18,7 @@ from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.MWType import MWType from discopop_explorer.enums.EdgeType import EdgeType -from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo +from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.task_parallelism.classes import ( TaskParallelismInfo, TPIType, diff --git a/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py b/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py index ee46fc17c..131320c11 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py @@ -13,7 +13,7 @@ from discopop_explorer.classes.DummyNode import DummyNode from discopop_explorer.enums.MWType import MWType from discopop_explorer.parser import parse_inputs -from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo +from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.do_all_detector import run_detection as detect_do_all from discopop_explorer.pattern_detectors.reduction_detector import ReductionInfo, run_detection as detect_reduction from discopop_explorer.pattern_detectors.task_parallelism.classes import ( diff --git a/discopop_library/CodeGenerator/CodeGenerator.py b/discopop_library/CodeGenerator/CodeGenerator.py index 5bfd952e1..82db5fa67 100644 --- a/discopop_library/CodeGenerator/CodeGenerator.py +++ b/discopop_library/CodeGenerator/CodeGenerator.py @@ -10,7 +10,7 @@ import jsons # type: ignore -from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo +from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_library.CodeGenerator.classes.ContentBuffer import ContentBuffer from discopop_library.CodeGenerator.classes.UnpackedSuggestion import UnpackedSuggestion from discopop_library.discopop_optimizer.classes.system.devices.DeviceTypeEnum import DeviceTypeEnum diff --git a/discopop_library/discopop_optimizer/classes/nodes/GenericNode.py b/discopop_library/discopop_optimizer/classes/nodes/GenericNode.py index 58a134899..14b019118 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/GenericNode.py +++ b/discopop_library/discopop_optimizer/classes/nodes/GenericNode.py @@ -11,7 +11,7 @@ from sympy import Symbol, Function, Integer # type: ignore from discopop_explorer.aliases.NodeID import NodeID -from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo +from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel from typing import TYPE_CHECKING diff --git a/discopop_library/discopop_optimizer/classes/system/devices/Device.py b/discopop_library/discopop_optimizer/classes/system/devices/Device.py index fb350c898..3633feec3 100644 --- a/discopop_library/discopop_optimizer/classes/system/devices/Device.py +++ b/discopop_library/discopop_optimizer/classes/system/devices/Device.py @@ -10,7 +10,7 @@ from sympy import Expr, Float, Symbol from sympy import Integer -from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo +from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_library.discopop_optimizer.classes.system.devices.DeviceTypeEnum import DeviceTypeEnum diff --git a/discopop_library/discopop_optimizer/classes/system/devices/GPU.py b/discopop_library/discopop_optimizer/classes/system/devices/GPU.py index edd9fa5ee..9d51c9e98 100644 --- a/discopop_library/discopop_optimizer/classes/system/devices/GPU.py +++ b/discopop_library/discopop_optimizer/classes/system/devices/GPU.py @@ -9,7 +9,7 @@ from sympy import Integer -from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo +from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_library.discopop_optimizer.classes.system.devices.Device import Device from discopop_library.discopop_optimizer.classes.system.devices.DeviceTypeEnum import DeviceTypeEnum diff --git a/discopop_library/result_classes/PatternStorage.py b/discopop_library/result_classes/PatternStorage.py index 0a415f72a..df38eef60 100644 --- a/discopop_library/result_classes/PatternStorage.py +++ b/discopop_library/result_classes/PatternStorage.py @@ -9,7 +9,7 @@ from typing import List, cast from discopop_explorer.pattern_detectors.PatternBase import PatternBase -from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo +from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.do_all_detector import DoAllInfo from discopop_explorer.pattern_detectors.geometric_decomposition_detector import GDInfo from discopop_explorer.pattern_detectors.pipeline_detector import PipelineInfo From 4aeb0931e86363b50dd555a1cd76e6a48110420c Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 31 Jul 2024 10:04:06 +0200 Subject: [PATCH 060/105] refactor: PatternBase --- .../patterns}/PatternBase.py | 0 discopop_explorer/classes/patterns/PatternInfo.py | 2 +- discopop_explorer/json_serializer.py | 2 +- discopop_library/result_classes/MergedPattern.py | 8 +------- discopop_library/result_classes/OptimizerOutputPattern.py | 2 +- discopop_library/result_classes/PatternStorage.py | 2 +- 6 files changed, 5 insertions(+), 11 deletions(-) rename discopop_explorer/{pattern_detectors => classes/patterns}/PatternBase.py (100%) diff --git a/discopop_explorer/pattern_detectors/PatternBase.py b/discopop_explorer/classes/patterns/PatternBase.py similarity index 100% rename from discopop_explorer/pattern_detectors/PatternBase.py rename to discopop_explorer/classes/patterns/PatternBase.py diff --git a/discopop_explorer/classes/patterns/PatternInfo.py b/discopop_explorer/classes/patterns/PatternInfo.py index e8db06ee2..881d291a9 100644 --- a/discopop_explorer/classes/patterns/PatternInfo.py +++ b/discopop_explorer/classes/patterns/PatternInfo.py @@ -6,7 +6,7 @@ # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. from typing import Optional -from discopop_explorer.pattern_detectors.PatternBase import PatternBase +from discopop_explorer.classes.patterns.PatternBase import PatternBase from discopop_library.discopop_optimizer.classes.system.devices.DeviceTypeEnum import DeviceTypeEnum diff --git a/discopop_explorer/json_serializer.py b/discopop_explorer/json_serializer.py index 35579efc6..ed853ff4f 100644 --- a/discopop_explorer/json_serializer.py +++ b/discopop_explorer/json_serializer.py @@ -8,7 +8,7 @@ from json import JSONEncoder from typing import Dict, Any -from discopop_explorer.pattern_detectors.PatternBase import PatternBase +from discopop_explorer.classes.patterns.PatternBase import PatternBase from discopop_library.discopop_optimizer.classes.context.Update import Update from discopop_library.discopop_optimizer.classes.types.DataAccessType import WriteDataAccess diff --git a/discopop_library/result_classes/MergedPattern.py b/discopop_library/result_classes/MergedPattern.py index 49efe92c1..1bc0de6a2 100644 --- a/discopop_library/result_classes/MergedPattern.py +++ b/discopop_library/result_classes/MergedPattern.py @@ -7,16 +7,10 @@ # directory for details. -import json -from typing import Any, Dict, List +from typing import List from discopop_explorer.classes.Node import Node -from discopop_explorer.pattern_detectors.PatternBase import PatternBase -from discopop_library.PatternIdManagement.unique_pattern_id import get_unique_pattern_id from discopop_library.discopop_optimizer.Variables.Experiment import Experiment -from discopop_library.discopop_optimizer.classes.context.Update import Update, construct_update_from_dict -from discopop_library.discopop_optimizer.classes.system.devices.DeviceTypeEnum import DeviceTypeEnum -from discopop_library.discopop_optimizer.classes.types.Aliases import DeviceID from discopop_library.result_classes.OptimizerOutputPattern import OptimizerOutputPattern diff --git a/discopop_library/result_classes/OptimizerOutputPattern.py b/discopop_library/result_classes/OptimizerOutputPattern.py index 6fefaee68..2867028f8 100644 --- a/discopop_library/result_classes/OptimizerOutputPattern.py +++ b/discopop_library/result_classes/OptimizerOutputPattern.py @@ -10,7 +10,7 @@ import json from typing import Any, Dict, List from discopop_explorer.classes.Node import Node -from discopop_explorer.pattern_detectors.PatternBase import PatternBase +from discopop_explorer.classes.patterns.PatternBase import PatternBase from discopop_library.PatternIdManagement.unique_pattern_id import get_unique_pattern_id from discopop_library.discopop_optimizer.Variables.Experiment import Experiment diff --git a/discopop_library/result_classes/PatternStorage.py b/discopop_library/result_classes/PatternStorage.py index df38eef60..f9ed1ce52 100644 --- a/discopop_library/result_classes/PatternStorage.py +++ b/discopop_library/result_classes/PatternStorage.py @@ -8,7 +8,7 @@ from typing import List, cast -from discopop_explorer.pattern_detectors.PatternBase import PatternBase +from discopop_explorer.classes.patterns.PatternBase import PatternBase from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.do_all_detector import DoAllInfo from discopop_explorer.pattern_detectors.geometric_decomposition_detector import GDInfo From 4d80138f0d67ea65ad373470612a87c8762ae65d Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 31 Jul 2024 10:06:11 +0200 Subject: [PATCH 061/105] refactor: moved utility --- discopop_explorer/discopop_explorer.py | 2 +- .../{ => utilities}/generate_Data_CUInst.py | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) rename discopop_explorer/{ => utilities}/generate_Data_CUInst.py (94%) diff --git a/discopop_explorer/discopop_explorer.py b/discopop_explorer/discopop_explorer.py index c03419db5..2347b14a3 100644 --- a/discopop_explorer/discopop_explorer.py +++ b/discopop_explorer/discopop_explorer.py @@ -193,7 +193,7 @@ def run(arguments: ExplorerArguments) -> None: try: if arguments.generate_data_cu_inst is not None: # start generation of Data_CUInst and stop execution afterwards - from .generate_Data_CUInst import wrapper as generate_data_cuinst_wrapper + from discopop_explorer.utilities.generate_Data_CUInst import wrapper as generate_data_cuinst_wrapper generate_data_cuinst_wrapper( arguments.cu_xml_file, diff --git a/discopop_explorer/generate_Data_CUInst.py b/discopop_explorer/utilities/generate_Data_CUInst.py similarity index 94% rename from discopop_explorer/generate_Data_CUInst.py rename to discopop_explorer/utilities/generate_Data_CUInst.py index c42eba4d3..a7356aa99 100644 --- a/discopop_explorer/generate_Data_CUInst.py +++ b/discopop_explorer/utilities/generate_Data_CUInst.py @@ -12,15 +12,15 @@ from discopop_explorer.classes.PEGraphX import ( PEGraphX, ) -from .classes.FunctionNode import FunctionNode -from .classes.LoopNode import LoopNode -from .classes.CUNode import CUNode -from .classes.Node import Node -from .aliases.LineID import LineID -from .aliases.NodeID import NodeID -from .enums.DepType import DepType -from .enums.EdgeType import EdgeType -from .parser import parse_inputs +from discopop_explorer.classes.FunctionNode import FunctionNode +from discopop_explorer.classes.LoopNode import LoopNode +from discopop_explorer.classes.CUNode import CUNode +from discopop_explorer.classes.Node import Node +from discopop_explorer.aliases.LineID import LineID +from discopop_explorer.aliases.NodeID import NodeID +from discopop_explorer.enums.DepType import DepType +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.parser import parse_inputs def __collect_children_ids(pet: PEGraphX, parent_id: NodeID, children_ids: List[NodeID]) -> List[NodeID]: From fd168fb79167c51c31c659bac1b80aa8d5a0e1c3 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 31 Jul 2024 10:19:05 +0200 Subject: [PATCH 062/105] refactor: restructuring --- discopop_explorer/classes/LoopNode.py | 2 +- discopop_explorer/classes/Node.py | 2 +- discopop_explorer/classes/PEGraphX.py | 6 +++-- discopop_explorer/discopop_explorer.py | 2 +- .../simple_gpu_patterns/GPULoop.py | 2 +- .../task_parallelism_detector.py | 2 +- .../PEGraphConstructionUtilities.py} | 2 +- .../utilities/PEGraphConstruction/__init__.py | 0 .../classes/DependenceItem.py | 22 ++++++++++++++++ .../PEGraphConstruction/classes/LoopData.py | 18 +++++++++++++ .../PEGraphConstruction/classes/__init__.py | 0 .../PEGraphConstruction}/parser.py | 26 ++----------------- .../utilities/generate_Data_CUInst.py | 2 +- discopop_explorer/utils.py | 2 +- 14 files changed, 54 insertions(+), 34 deletions(-) rename discopop_explorer/utilities/{PEGraphConstruction.py => PEGraphConstruction/PEGraphConstructionUtilities.py} (98%) create mode 100644 discopop_explorer/utilities/PEGraphConstruction/__init__.py create mode 100644 discopop_explorer/utilities/PEGraphConstruction/classes/DependenceItem.py create mode 100644 discopop_explorer/utilities/PEGraphConstruction/classes/LoopData.py create mode 100644 discopop_explorer/utilities/PEGraphConstruction/classes/__init__.py rename discopop_explorer/{ => utilities/PEGraphConstruction}/parser.py (95%) diff --git a/discopop_explorer/classes/LoopNode.py b/discopop_explorer/classes/LoopNode.py index c97087394..4cce15d34 100644 --- a/discopop_explorer/classes/LoopNode.py +++ b/discopop_explorer/classes/LoopNode.py @@ -15,7 +15,7 @@ from discopop_explorer.classes.Node import Node from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.enums.NodeType import NodeType -from discopop_explorer.parser import LoopData +from discopop_explorer.utilities.PEGraphConstruction.classes.LoopData import LoopData # Data.xml: type="2" diff --git a/discopop_explorer/classes/Node.py b/discopop_explorer/classes/Node.py index 5d2e005fa..a9872ef0d 100644 --- a/discopop_explorer/classes/Node.py +++ b/discopop_explorer/classes/Node.py @@ -10,7 +10,7 @@ from typing import Optional, List, Dict, Any from discopop_explorer.classes.PEGraphX import PEGraphX -from discopop_explorer.utilities.PEGraphConstruction import parse_id +from discopop_explorer.utilities.PEGraphConstruction.PEGraphConstructionUtilities import parse_id from discopop_explorer.classes.FunctionNode import FunctionNode from discopop_explorer.aliases.LineID import LineID from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_explorer/classes/PEGraphX.py b/discopop_explorer/classes/PEGraphX.py index d202ddc5b..3a3e6432a 100644 --- a/discopop_explorer/classes/PEGraphX.py +++ b/discopop_explorer/classes/PEGraphX.py @@ -33,8 +33,10 @@ from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.enums.NodeType import NodeType -from discopop_explorer.parser import LoopData, readlineToCUIdMap, writelineToCUIdMap, DependenceItem -from discopop_explorer.utilities.PEGraphConstruction import parse_dependency, parse_cu +from discopop_explorer.utilities.PEGraphConstruction.parser import readlineToCUIdMap, writelineToCUIdMap +from discopop_explorer.utilities.PEGraphConstruction.classes.LoopData import LoopData +from discopop_explorer.utilities.PEGraphConstruction.classes.DependenceItem import DependenceItem +from discopop_explorer.utilities.PEGraphConstruction.PEGraphConstructionUtilities import parse_dependency, parse_cu from discopop_explorer.variable import Variable global_pet = None diff --git a/discopop_explorer/discopop_explorer.py b/discopop_explorer/discopop_explorer.py index 2347b14a3..4c6f18b7d 100644 --- a/discopop_explorer/discopop_explorer.py +++ b/discopop_explorer/discopop_explorer.py @@ -31,7 +31,7 @@ from discopop_library.result_classes.DetectionResult import DetectionResult from discopop_explorer.classes.PEGraphX import PEGraphX from .json_serializer import PatternBaseSerializer -from .parser import parse_inputs +from discopop_explorer.utilities.PEGraphConstruction.parser import parse_inputs from .pattern_detection import PatternDetectorX from discopop_library.HostpotLoader.hostpot_loader import run as load_hotspots diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py index 556ff66e0..b3e46b75b 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py @@ -12,7 +12,7 @@ from discopop_explorer.classes.PEGraphX import ( PEGraphX, ) -from ...utilities.PEGraphConstruction import parse_id +from ...utilities.PEGraphConstruction.PEGraphConstructionUtilities import parse_id from ...classes.FunctionNode import FunctionNode from ...classes.LoopNode import LoopNode from ...classes.CUNode import CUNode diff --git a/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py b/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py index 131320c11..820b99576 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py @@ -12,7 +12,7 @@ from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.classes.DummyNode import DummyNode from discopop_explorer.enums.MWType import MWType -from discopop_explorer.parser import parse_inputs +from discopop_explorer.utilities.PEGraphConstruction.parser import parse_inputs from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.do_all_detector import run_detection as detect_do_all from discopop_explorer.pattern_detectors.reduction_detector import ReductionInfo, run_detection as detect_reduction diff --git a/discopop_explorer/utilities/PEGraphConstruction.py b/discopop_explorer/utilities/PEGraphConstruction/PEGraphConstructionUtilities.py similarity index 98% rename from discopop_explorer/utilities/PEGraphConstruction.py rename to discopop_explorer/utilities/PEGraphConstruction/PEGraphConstructionUtilities.py index 528d3d63e..49345a65d 100644 --- a/discopop_explorer/utilities/PEGraphConstruction.py +++ b/discopop_explorer/utilities/PEGraphConstruction/PEGraphConstructionUtilities.py @@ -22,7 +22,7 @@ from discopop_explorer.enums.DepType import DepType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.enums.NodeType import NodeType -from discopop_explorer.parser import DependenceItem +from discopop_explorer.utilities.PEGraphConstruction.classes.DependenceItem import DependenceItem from discopop_explorer.variable import Variable diff --git a/discopop_explorer/utilities/PEGraphConstruction/__init__.py b/discopop_explorer/utilities/PEGraphConstruction/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/discopop_explorer/utilities/PEGraphConstruction/classes/DependenceItem.py b/discopop_explorer/utilities/PEGraphConstruction/classes/DependenceItem.py new file mode 100644 index 000000000..1892c86ce --- /dev/null +++ b/discopop_explorer/utilities/PEGraphConstruction/classes/DependenceItem.py @@ -0,0 +1,22 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from dataclasses import dataclass +from typing import Any + + +@dataclass +class DependenceItem(object): + sink: Any + source: Any + type: Any + var_name: Any + memory_region: Any + is_gep_result_dependency: bool + metadata: Any + # TODO improve typing diff --git a/discopop_explorer/utilities/PEGraphConstruction/classes/LoopData.py b/discopop_explorer/utilities/PEGraphConstruction/classes/LoopData.py new file mode 100644 index 000000000..5f9516fc9 --- /dev/null +++ b/discopop_explorer/utilities/PEGraphConstruction/classes/LoopData.py @@ -0,0 +1,18 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from dataclasses import dataclass + + +@dataclass +class LoopData(object): + line_id: str # file_id:line_nr + total_iteration_count: int + entry_count: int + average_iteration_count: int + maximum_iteration_count: int diff --git a/discopop_explorer/utilities/PEGraphConstruction/classes/__init__.py b/discopop_explorer/utilities/PEGraphConstruction/classes/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/discopop_explorer/parser.py b/discopop_explorer/utilities/PEGraphConstruction/parser.py similarity index 95% rename from discopop_explorer/parser.py rename to discopop_explorer/utilities/PEGraphConstruction/parser.py index 89abc5d59..3d2da59af 100644 --- a/discopop_explorer/parser.py +++ b/discopop_explorer/utilities/PEGraphConstruction/parser.py @@ -11,14 +11,14 @@ import re import warnings from collections import defaultdict -from dataclasses import dataclass from os.path import abspath, dirname from typing import Any, Dict, List, Optional, Tuple from lxml import objectify # type:ignore from lxml.objectify import ObjectifiedElement # type: ignore -import discopop_explorer.classes.Node +from discopop_explorer.utilities.PEGraphConstruction.classes.DependenceItem import DependenceItem +from discopop_explorer.utilities.PEGraphConstruction.classes.LoopData import LoopData # Map to record which line belongs to read set of nodes. LID -> NodeIds readlineToCUIdMap = defaultdict(set) # type: ignore @@ -28,28 +28,6 @@ lineToCUIdMap = defaultdict(set) # type: ignore -@dataclass -class DependenceItem(object): - sink: Any - source: Any - type: Any - var_name: Any - memory_region: Any - is_gep_result_dependency: bool - metadata: Any - # TODO improve typing - - -# TODO move this class to a better place, we need it not only for parsing -@dataclass -class LoopData(object): - line_id: str # file_id:line_nr - total_iteration_count: int - entry_count: int - average_iteration_count: int - maximum_iteration_count: int - - def __parse_xml_input(xml_fd: TextIOWrapper) -> Dict[str, ObjectifiedElement]: xml_content = "" for line in xml_fd.readlines(): diff --git a/discopop_explorer/utilities/generate_Data_CUInst.py b/discopop_explorer/utilities/generate_Data_CUInst.py index a7356aa99..6ce0b0c25 100644 --- a/discopop_explorer/utilities/generate_Data_CUInst.py +++ b/discopop_explorer/utilities/generate_Data_CUInst.py @@ -20,7 +20,7 @@ from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.DepType import DepType from discopop_explorer.enums.EdgeType import EdgeType -from discopop_explorer.parser import parse_inputs +from discopop_explorer.utilities.PEGraphConstruction.parser import parse_inputs def __collect_children_ids(pet: PEGraphX, parent_id: NodeID, children_ids: List[NodeID]) -> List[NodeID]: diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index 06b8ae9e6..befb6966f 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -28,7 +28,7 @@ from .enums.NodeType import NodeType from .enums.DepType import DepType from .enums.EdgeType import EdgeType -from .parser import LoopData +from .utilities.PEGraphConstruction.classes.LoopData import LoopData from .variable import Variable loop_data: Dict[LineID, int] = {} From f41912f3873368fc06718ee150178400e8ee3ecf Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 31 Jul 2024 10:21:50 +0200 Subject: [PATCH 063/105] refactor: moved variable --- discopop_explorer/{ => classes}/variable.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename discopop_explorer/{ => classes}/variable.py (100%) diff --git a/discopop_explorer/variable.py b/discopop_explorer/classes/variable.py similarity index 100% rename from discopop_explorer/variable.py rename to discopop_explorer/classes/variable.py From ca0819c5209473f0150f46d6b8e71296d4d1929b Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 31 Jul 2024 10:47:25 +0200 Subject: [PATCH 064/105] fix: modified .gitignore --- .gitignore | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index f8c226bf9..6ad66132a 100644 --- a/.gitignore +++ b/.gitignore @@ -72,8 +72,8 @@ coverage.xml profiling_stats.txt # Code structure diagrams -classes.png -packages.png +classes.svg +packages.svg # Translations *.mo From 2ed72870c4556ecf85d3205e39a3548c665914fa Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 31 Jul 2024 11:02:47 +0200 Subject: [PATCH 065/105] refactor: get_parent_id --- discopop_explorer/classes/FunctionNode.py | 5 +++-- discopop_explorer/classes/Node.py | 18 ------------------ discopop_explorer/classes/PEGraphX.py | 18 ++++++++++++++++++ scripts/dev/check-commit-msg.py | 2 +- 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/discopop_explorer/classes/FunctionNode.py b/discopop_explorer/classes/FunctionNode.py index d6c2978f2..0a41ad6f1 100644 --- a/discopop_explorer/classes/FunctionNode.py +++ b/discopop_explorer/classes/FunctionNode.py @@ -122,8 +122,9 @@ def get_immediate_post_dominators(self, pet: PEGraphX) -> Dict[NodeID, NodeID]: visited = set() use_original = False while ( - pet.node_at(node_id).get_parent_id(pet) == pet.node_at(post_dom_id).get_parent_id(pet) - and type(pet.node_at(cast(NodeID, pet.node_at(post_dom_id).get_parent_id(pet)))) != FunctionNode + pet.get_node_parent_id(pet.node_at(node_id)) == pet.get_node_parent_id(pet.node_at(post_dom_id)) + and type(pet.node_at(cast(NodeID, pet.get_node_parent_id(pet.node_at(post_dom_id))))) + != FunctionNode ): if post_dom_id in visited: # cycle detected! diff --git a/discopop_explorer/classes/Node.py b/discopop_explorer/classes/Node.py index a9872ef0d..ad750552d 100644 --- a/discopop_explorer/classes/Node.py +++ b/discopop_explorer/classes/Node.py @@ -9,7 +9,6 @@ from typing import Optional, List, Dict, Any -from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.utilities.PEGraphConstruction.PEGraphConstructionUtilities import parse_id from discopop_explorer.classes.FunctionNode import FunctionNode from discopop_explorer.aliases.LineID import LineID @@ -97,20 +96,3 @@ def __eq__(self, other: Any) -> bool: def __hash__(self) -> int: return hash(self.id) - - def get_parent_id(self, pet: PEGraphX) -> Optional[NodeID]: - parents = [s for s, t, d in pet.in_edges(self.id, EdgeType.CHILD)] - if len(parents) == 0: - return None - elif len(parents) == 1: - return parents[0] - else: - # it is possible that a node has a function-type and e.g. loop type parent - # in this case, return the non-function type parent, since it will be a child of the function itself. - if len(parents) > 2: - raise ValueError("Node: ", self.id, "has too many parents!") - else: - for parent in parents: - if type(pet.node_at(parent)) != FunctionNode: - return parent - return None diff --git a/discopop_explorer/classes/PEGraphX.py b/discopop_explorer/classes/PEGraphX.py index 3a3e6432a..5e1133130 100644 --- a/discopop_explorer/classes/PEGraphX.py +++ b/discopop_explorer/classes/PEGraphX.py @@ -572,6 +572,24 @@ def __cu_equal__(self, cu_1: Node, cu_2: Node) -> bool: return True return False + def get_node_parent_id(self, node: Node) -> Optional[NodeID]: + """Returns the id of the FunctionNode which is the parent of the given node""" + parents = [s for s, t, d in self.in_edges(node.id, EdgeType.CHILD)] + if len(parents) == 0: + return None + elif len(parents) == 1: + return parents[0] + else: + # it is possible that a node has a function-type and e.g. loop type parent + # in this case, return the non-function type parent, since it will be a child of the function itself. + if len(parents) > 2: + raise ValueError("Node: ", node.id, "has too many parents!") + else: + for parent in parents: + if type(self.node_at(parent)) != FunctionNode: + return parent + return None + def direct_successors(self, root: Node) -> List[Node]: """Gets only direct successors of any type diff --git a/scripts/dev/check-commit-msg.py b/scripts/dev/check-commit-msg.py index f07141d76..a21ce3f41 100644 --- a/scripts/dev/check-commit-msg.py +++ b/scripts/dev/check-commit-msg.py @@ -20,7 +20,7 @@ commit_msg = f.read() commit_msg = commit_msg.replace("\n", "") -pattern = re.compile("^(feat|fix|test|chore|refactor|doc|docs|perf|ci|build|style)(\(.+\))?(\[.+\])?:.+$") +pattern = re.compile("^(feat|fix|test|chore|refactor|doc|docs|perf|wip|ci|build|style)(\(.+\))?(\[.+\])?:.+$") matches = bool(pattern.match(commit_msg)) if matches: From 43ac09caaa16534b0dc92b3b778a8a661d4bfe7f Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 31 Jul 2024 11:07:33 +0200 Subject: [PATCH 066/105] refactor: resolved circular import --- discopop_explorer/classes/Node.py | 9 ++++++--- .../PEGraphConstruction/PEGraphConstructionUtilities.py | 6 +++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/discopop_explorer/classes/Node.py b/discopop_explorer/classes/Node.py index ad750552d..a00940487 100644 --- a/discopop_explorer/classes/Node.py +++ b/discopop_explorer/classes/Node.py @@ -7,9 +7,8 @@ # directory for details. from __future__ import annotations -from typing import Optional, List, Dict, Any +from typing import Optional, List, Dict, Any, Tuple -from discopop_explorer.utilities.PEGraphConstruction.PEGraphConstructionUtilities import parse_id from discopop_explorer.classes.FunctionNode import FunctionNode from discopop_explorer.aliases.LineID import LineID from discopop_explorer.aliases.NodeID import NodeID @@ -49,7 +48,7 @@ class Node: def __init__(self, node_id: NodeID): self.id = node_id - self.file_id, self.node_id = parse_id(node_id) + self.file_id, self.node_id = self.__parse_id(node_id) # @classmethod # def from_kwargs(cls, node_id: NodeID, **kwargs) -> Node: @@ -96,3 +95,7 @@ def __eq__(self, other: Any) -> bool: def __hash__(self) -> int: return hash(self.id) + + def __parse_id(self, node_id: str) -> Tuple[int, int]: + split = node_id.split(":") + return int(split[0]), int(split[1]) diff --git a/discopop_explorer/utilities/PEGraphConstruction/PEGraphConstructionUtilities.py b/discopop_explorer/utilities/PEGraphConstruction/PEGraphConstructionUtilities.py index 49345a65d..d653cc65c 100644 --- a/discopop_explorer/utilities/PEGraphConstruction/PEGraphConstructionUtilities.py +++ b/discopop_explorer/utilities/PEGraphConstruction/PEGraphConstructionUtilities.py @@ -138,13 +138,13 @@ def parse_cu(node: ObjectifiedElement) -> Node: else: assert False, "invalid NodeType" - _, n.start_line = parse_id(node.get("startsAtLine")) - _, n.end_line = parse_id(node.get("endsAtLine")) + _, n.start_line = __parse_id(node.get("startsAtLine")) + _, n.end_line = __parse_id(node.get("endsAtLine")) n.name = node.get("name") return n -def parse_id(node_id: str) -> Tuple[int, int]: +def __parse_id(node_id: str) -> Tuple[int, int]: split = node_id.split(":") return int(split[0]), int(split[1]) From 15f81f7846f7f37ce43d68b1871567b6f6b323a4 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 31 Jul 2024 12:47:15 +0200 Subject: [PATCH 067/105] fix: minor --- discopop_explorer/classes/CUNode.py | 2 +- discopop_explorer/classes/DummyNode.py | 2 +- discopop_explorer/classes/FunctionNode.py | 8 +++++--- discopop_explorer/classes/LoopNode.py | 6 ++++-- discopop_explorer/classes/Node.py | 8 ++------ discopop_explorer/classes/PEGraphX.py | 2 +- discopop_explorer/pattern_detection.py | 2 +- .../simple_gpu_patterns/GPULoop.py | 4 ++-- .../simple_gpu_patterns/GPUMemory.py | 2 +- .../simple_gpu_patterns/GPURegions.py | 2 +- .../simple_gpu_patterns/gpu_pattern_detector.py | 2 +- .../PEGraphConstructionUtilities.py | 14 +++++--------- discopop_explorer/utils.py | 7 +++++++ .../UpdateOptimization/AddRangesToUpdates.py | 2 +- 14 files changed, 33 insertions(+), 30 deletions(-) diff --git a/discopop_explorer/classes/CUNode.py b/discopop_explorer/classes/CUNode.py index fe49ac963..010d8ed5d 100644 --- a/discopop_explorer/classes/CUNode.py +++ b/discopop_explorer/classes/CUNode.py @@ -12,7 +12,7 @@ from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.classes.Node import Node from discopop_explorer.enums.NodeType import NodeType -from discopop_explorer.variable import Variable +from discopop_explorer.classes.variable import Variable # Data.xml: type="0" diff --git a/discopop_explorer/classes/DummyNode.py b/discopop_explorer/classes/DummyNode.py index 8685379c4..2ca58118b 100644 --- a/discopop_explorer/classes/DummyNode.py +++ b/discopop_explorer/classes/DummyNode.py @@ -12,7 +12,7 @@ from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.classes.Node import Node from discopop_explorer.enums.NodeType import NodeType -from discopop_explorer.variable import Variable +from discopop_explorer.classes.variable import Variable # Data.xml: type="3" diff --git a/discopop_explorer/classes/FunctionNode.py b/discopop_explorer/classes/FunctionNode.py index 0a41ad6f1..3c6220444 100644 --- a/discopop_explorer/classes/FunctionNode.py +++ b/discopop_explorer/classes/FunctionNode.py @@ -7,11 +7,10 @@ # directory for details. from __future__ import annotations -from typing import List, Optional, Dict, Set, cast, Tuple +from typing import TYPE_CHECKING, List, Optional, Dict, Set, cast, Tuple import networkx as nx # type: ignore -from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.classes.CUNode import CUNode @@ -19,7 +18,10 @@ from discopop_explorer.classes.Node import Node from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.enums.NodeType import NodeType -from discopop_explorer.variable import Variable +from discopop_explorer.classes.variable import Variable + +if TYPE_CHECKING: + from discopop_explorer.classes.PEGraphX import PEGraphX # Data.xml: type="1" diff --git a/discopop_explorer/classes/LoopNode.py b/discopop_explorer/classes/LoopNode.py index 4cce15d34..4d3fa7f57 100644 --- a/discopop_explorer/classes/LoopNode.py +++ b/discopop_explorer/classes/LoopNode.py @@ -7,9 +7,8 @@ # directory for details. from __future__ import annotations -from typing import Optional, List +from typing import TYPE_CHECKING, Optional, List -from discopop_explorer.classes.PEGraphX import PEGraphX from discopop_explorer.classes.FunctionNode import FunctionNode from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.classes.Node import Node @@ -17,6 +16,9 @@ from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.utilities.PEGraphConstruction.classes.LoopData import LoopData +if TYPE_CHECKING: + from discopop_explorer.classes.PEGraphX import PEGraphX + # Data.xml: type="2" class LoopNode(Node): diff --git a/discopop_explorer/classes/Node.py b/discopop_explorer/classes/Node.py index a00940487..f91c01b44 100644 --- a/discopop_explorer/classes/Node.py +++ b/discopop_explorer/classes/Node.py @@ -9,12 +9,12 @@ from typing import Optional, List, Dict, Any, Tuple -from discopop_explorer.classes.FunctionNode import FunctionNode from discopop_explorer.aliases.LineID import LineID from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.enums.MWType import MWType from discopop_explorer.enums.NodeType import NodeType +from discopop_explorer.utils import parse_id # TODO make the Node class abstract @@ -48,7 +48,7 @@ class Node: def __init__(self, node_id: NodeID): self.id = node_id - self.file_id, self.node_id = self.__parse_id(node_id) + self.file_id, self.node_id = parse_id(node_id) # @classmethod # def from_kwargs(cls, node_id: NodeID, **kwargs) -> Node: @@ -95,7 +95,3 @@ def __eq__(self, other: Any) -> bool: def __hash__(self) -> int: return hash(self.id) - - def __parse_id(self, node_id: str) -> Tuple[int, int]: - split = node_id.split(":") - return int(split[0]), int(split[1]) diff --git a/discopop_explorer/classes/PEGraphX.py b/discopop_explorer/classes/PEGraphX.py index 5e1133130..56089c16a 100644 --- a/discopop_explorer/classes/PEGraphX.py +++ b/discopop_explorer/classes/PEGraphX.py @@ -37,7 +37,7 @@ from discopop_explorer.utilities.PEGraphConstruction.classes.LoopData import LoopData from discopop_explorer.utilities.PEGraphConstruction.classes.DependenceItem import DependenceItem from discopop_explorer.utilities.PEGraphConstruction.PEGraphConstructionUtilities import parse_dependency, parse_cu -from discopop_explorer.variable import Variable +from discopop_explorer.classes.variable import Variable global_pet = None diff --git a/discopop_explorer/pattern_detection.py b/discopop_explorer/pattern_detection.py index 1230eef5b..f7f2d156b 100644 --- a/discopop_explorer/pattern_detection.py +++ b/discopop_explorer/pattern_detection.py @@ -15,7 +15,7 @@ from discopop_explorer.pattern_detectors.task_parallelism.task_parallelism_detector import ( build_preprocessed_graph_and_run_detection as detect_tp, ) -from discopop_explorer.variable import Variable +from discopop_explorer.classes.variable import Variable from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType from discopop_library.HostpotLoader.HotspotType import HotspotType from discopop_library.JSONHandler.JSONHandler import read_patterns_from_json_to_json diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py index b3e46b75b..4fdfea2fd 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py @@ -12,7 +12,6 @@ from discopop_explorer.classes.PEGraphX import ( PEGraphX, ) -from ...utilities.PEGraphConstruction.PEGraphConstructionUtilities import parse_id from ...classes.FunctionNode import FunctionNode from ...classes.LoopNode import LoopNode from ...classes.CUNode import CUNode @@ -24,6 +23,7 @@ from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.utils import ( __get_dep_of_type as get_dep_of_type, + parse_id, ) from discopop_explorer.utils import ( is_scalar_val, @@ -40,7 +40,7 @@ is_first_written, is_read_in_subtree, ) -from discopop_explorer.variable import Variable +from discopop_explorer.classes.variable import Variable from discopop_library.MemoryRegions.utils import get_sizes_of_memory_regions from discopop_library.result_classes.DetectionResult import DetectionResult from .GPUMemory import getCalledFunctions, map_node diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py index dca871d70..20362eb9c 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py @@ -21,7 +21,7 @@ from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.DepType import DepType from discopop_explorer.utils import is_func_arg, is_global, __get_dep_of_type as get_dep_of_type -from discopop_explorer.variable import Variable +from discopop_explorer.classes.variable import Variable def map_node(pet: PEGraphX, nodeID: NodeID) -> Node: diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py index d800a3b86..13a51462f 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py @@ -20,7 +20,7 @@ from ...enums.NodeType import NodeType from ...enums.DepType import DepType from ...enums.EdgeType import EdgeType -from discopop_explorer.variable import Variable +from discopop_explorer.classes.variable import Variable from .GPULoop import GPULoopPattern from .GPUMemory import map_node from discopop_explorer.classes.patterns.PatternInfo import PatternInfo diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py index a3a3bfac3..d86d33ae4 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py @@ -19,7 +19,7 @@ GPURegions, GPURegionInfo, ) -from discopop_explorer.variable import Variable +from discopop_explorer.classes.variable import Variable from discopop_library.result_classes.DetectionResult import DetectionResult diff --git a/discopop_explorer/utilities/PEGraphConstruction/PEGraphConstructionUtilities.py b/discopop_explorer/utilities/PEGraphConstruction/PEGraphConstructionUtilities.py index d653cc65c..0718a9c62 100644 --- a/discopop_explorer/utilities/PEGraphConstruction/PEGraphConstructionUtilities.py +++ b/discopop_explorer/utilities/PEGraphConstruction/PEGraphConstructionUtilities.py @@ -8,7 +8,7 @@ from __future__ import annotations -from typing import Union, Tuple +from typing import Union from lxml.objectify import ObjectifiedElement # type: ignore @@ -23,7 +23,8 @@ from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.utilities.PEGraphConstruction.classes.DependenceItem import DependenceItem -from discopop_explorer.variable import Variable +from discopop_explorer.classes.variable import Variable +from discopop_explorer.utils import parse_id def parse_dependency(dep: DependenceItem) -> Dependency: @@ -138,13 +139,8 @@ def parse_cu(node: ObjectifiedElement) -> Node: else: assert False, "invalid NodeType" - _, n.start_line = __parse_id(node.get("startsAtLine")) - _, n.end_line = __parse_id(node.get("endsAtLine")) + _, n.start_line = parse_id(node.get("startsAtLine")) + _, n.end_line = parse_id(node.get("endsAtLine")) n.name = node.get("name") return n - - -def __parse_id(node_id: str) -> Tuple[int, int]: - split = node_id.split(":") - return int(split[0]), int(split[1]) diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index befb6966f..a23ab76d8 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -5,6 +5,8 @@ # This software may be modified and distributed under the terms of # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. +from __future__ import annotations + import itertools from typing import Callable, List, Optional, Sequence, Set, Dict, Tuple, TypeVar, cast @@ -1149,3 +1151,8 @@ def filter_for_hotspots( # continue return list(result_set) + + +def parse_id(node_id: str) -> Tuple[int, int]: + split = node_id.split(":") + return int(split[0]), int(split[1]) diff --git a/discopop_library/discopop_optimizer/UpdateOptimization/AddRangesToUpdates.py b/discopop_library/discopop_optimizer/UpdateOptimization/AddRangesToUpdates.py index 457e9011a..5a2b178e8 100644 --- a/discopop_library/discopop_optimizer/UpdateOptimization/AddRangesToUpdates.py +++ b/discopop_library/discopop_optimizer/UpdateOptimization/AddRangesToUpdates.py @@ -9,7 +9,7 @@ from typing import Dict, List, Optional, Set, cast from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID -from discopop_explorer.variable import Variable +from discopop_explorer.classes.variable import Variable from discopop_library.discopop_optimizer.OptimizerArguments import OptimizerArguments from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.utilities.simple_utilities import data_at From eb39dd4be4e428b7b4b70b434de66b03094d834c Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 31 Jul 2024 12:57:13 +0200 Subject: [PATCH 068/105] refactor: prevent circular imports --- discopop_explorer/classes/CUNode.py | 8 ++-- discopop_explorer/classes/Node.py | 2 +- discopop_explorer/json_serializer.py | 2 +- .../pattern_detectors/do_all_detector.py | 2 +- .../geometric_decomposition_detector.py | 2 +- .../pattern_detectors/reduction_detector.py | 2 +- .../simple_gpu_patterns/GPULoop.py | 2 +- .../PEGraphConstructionUtilities.py | 2 +- .../PEGraphConstruction/ParserUtilities.py | 16 ++++++++ discopop_explorer/utils.py | 39 ++++++++----------- 10 files changed, 45 insertions(+), 32 deletions(-) create mode 100644 discopop_explorer/utilities/PEGraphConstruction/ParserUtilities.py diff --git a/discopop_explorer/classes/CUNode.py b/discopop_explorer/classes/CUNode.py index 010d8ed5d..11b9e0b42 100644 --- a/discopop_explorer/classes/CUNode.py +++ b/discopop_explorer/classes/CUNode.py @@ -7,12 +7,14 @@ # directory for details. from __future__ import annotations -from typing import List +from typing import TYPE_CHECKING, List -from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.classes.Node import Node from discopop_explorer.enums.NodeType import NodeType -from discopop_explorer.classes.variable import Variable + +if TYPE_CHECKING: + from discopop_explorer.classes.variable import Variable + from discopop_explorer.aliases.NodeID import NodeID # Data.xml: type="0" diff --git a/discopop_explorer/classes/Node.py b/discopop_explorer/classes/Node.py index f91c01b44..1941e6c76 100644 --- a/discopop_explorer/classes/Node.py +++ b/discopop_explorer/classes/Node.py @@ -14,7 +14,7 @@ from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.enums.MWType import MWType from discopop_explorer.enums.NodeType import NodeType -from discopop_explorer.utils import parse_id +from discopop_explorer.utilities.PEGraphConstruction.ParserUtilities import parse_id # TODO make the Node class abstract diff --git a/discopop_explorer/json_serializer.py b/discopop_explorer/json_serializer.py index ed853ff4f..4f644ed82 100644 --- a/discopop_explorer/json_serializer.py +++ b/discopop_explorer/json_serializer.py @@ -17,7 +17,7 @@ from .classes.Node import Node from .pattern_detectors.pipeline_detector import PipelineStage from .pattern_detectors.task_parallelism.classes import TPIType -from .variable import Variable +from .classes.variable import Variable def filter_members(d: Dict[Any, Any]) -> Dict[Any, Any]: diff --git a/discopop_explorer/pattern_detectors/do_all_detector.py b/discopop_explorer/pattern_detectors/do_all_detector.py index fc0b79442..a2dee40e1 100644 --- a/discopop_explorer/pattern_detectors/do_all_detector.py +++ b/discopop_explorer/pattern_detectors/do_all_detector.py @@ -29,7 +29,7 @@ from ..enums.DepType import DepType from ..enums.EdgeType import EdgeType from ..utils import classify_loop_variables, filter_for_hotspots -from ..variable import Variable +from ..classes.variable import Variable class DoAllInfo(PatternInfo): diff --git a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py index fd62243f8..e00c5a812 100644 --- a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py +++ b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py @@ -22,7 +22,7 @@ from ..aliases.NodeID import NodeID from ..enums.EdgeType import EdgeType from ..utils import classify_task_vars, filter_for_hotspots, get_child_loops -from ..variable import Variable +from ..classes.variable import Variable __loop_iterations: Dict[NodeID, int] = {} diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index 8dbb19280..0d43527cb 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -29,7 +29,7 @@ from ..enums.DepType import DepType from ..enums.EdgeType import EdgeType from ..utils import filter_for_hotspots, is_reduction_var, classify_loop_variables -from ..variable import Variable +from ..classes.variable import Variable class ReductionInfo(PatternInfo): diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py index 4fdfea2fd..39aa75460 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py @@ -23,8 +23,8 @@ from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.utils import ( __get_dep_of_type as get_dep_of_type, - parse_id, ) +from ...utilities.PEGraphConstruction.ParserUtilities import parse_id from discopop_explorer.utils import ( is_scalar_val, is_loop_index2, diff --git a/discopop_explorer/utilities/PEGraphConstruction/PEGraphConstructionUtilities.py b/discopop_explorer/utilities/PEGraphConstruction/PEGraphConstructionUtilities.py index 0718a9c62..741a500cc 100644 --- a/discopop_explorer/utilities/PEGraphConstruction/PEGraphConstructionUtilities.py +++ b/discopop_explorer/utilities/PEGraphConstruction/PEGraphConstructionUtilities.py @@ -24,7 +24,7 @@ from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.utilities.PEGraphConstruction.classes.DependenceItem import DependenceItem from discopop_explorer.classes.variable import Variable -from discopop_explorer.utils import parse_id +from discopop_explorer.utilities.PEGraphConstruction.ParserUtilities import parse_id def parse_dependency(dep: DependenceItem) -> Dependency: diff --git a/discopop_explorer/utilities/PEGraphConstruction/ParserUtilities.py b/discopop_explorer/utilities/PEGraphConstruction/ParserUtilities.py new file mode 100644 index 000000000..0eaf5ec86 --- /dev/null +++ b/discopop_explorer/utilities/PEGraphConstruction/ParserUtilities.py @@ -0,0 +1,16 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from __future__ import annotations + +from typing import Tuple + + +def parse_id(node_id: str) -> Tuple[int, int]: + split = node_id.split(":") + return int(split[0]), int(split[1]) diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index a23ab76d8..db21eb9d6 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -8,7 +8,7 @@ from __future__ import annotations import itertools -from typing import Callable, List, Optional, Sequence, Set, Dict, Tuple, TypeVar, cast +from typing import TYPE_CHECKING, Callable, List, Optional, Sequence, Set, Dict, Tuple, TypeVar, cast import numpy as np import warnings @@ -16,22 +16,22 @@ from discopop_library.HostpotLoader.HotspotType import HotspotType -from discopop_explorer.classes.PEGraphX import ( - PEGraphX, -) -from .classes.FunctionNode import FunctionNode -from .classes.LoopNode import LoopNode -from .classes.CUNode import CUNode -from .classes.Node import Node -from .classes.Dependency import Dependency -from .aliases.MemoryRegion import MemoryRegion -from .aliases.LineID import LineID -from .aliases.NodeID import NodeID -from .enums.NodeType import NodeType -from .enums.DepType import DepType -from .enums.EdgeType import EdgeType -from .utilities.PEGraphConstruction.classes.LoopData import LoopData -from .variable import Variable +from discopop_explorer.classes.FunctionNode import FunctionNode +from discopop_explorer.classes.LoopNode import LoopNode +from discopop_explorer.classes.CUNode import CUNode +from discopop_explorer.classes.Node import Node +from discopop_explorer.classes.Dependency import Dependency +from discopop_explorer.aliases.MemoryRegion import MemoryRegion +from discopop_explorer.aliases.LineID import LineID +from discopop_explorer.aliases.NodeID import NodeID +from discopop_explorer.enums.NodeType import NodeType +from discopop_explorer.enums.DepType import DepType +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.utilities.PEGraphConstruction.classes.LoopData import LoopData +from discopop_explorer.classes.variable import Variable + +if TYPE_CHECKING: + from discopop_explorer.classes.PEGraphX import PEGraphX loop_data: Dict[LineID, int] = {} @@ -1151,8 +1151,3 @@ def filter_for_hotspots( # continue return list(result_set) - - -def parse_id(node_id: str) -> Tuple[int, int]: - split = node_id.split(":") - return int(split[0]), int(split[1]) From a80e5556b9a6d713db2d2384c674eb7e276a4c1c Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 31 Jul 2024 13:09:52 +0200 Subject: [PATCH 069/105] refactor: minor move --- discopop_explorer/discopop_explorer.py | 2 +- discopop_explorer/utilities/general/__init__.py | 0 .../utilities/{ => general}/generate_Data_CUInst.py | 0 3 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 discopop_explorer/utilities/general/__init__.py rename discopop_explorer/utilities/{ => general}/generate_Data_CUInst.py (100%) diff --git a/discopop_explorer/discopop_explorer.py b/discopop_explorer/discopop_explorer.py index 4c6f18b7d..4a6ba0976 100644 --- a/discopop_explorer/discopop_explorer.py +++ b/discopop_explorer/discopop_explorer.py @@ -193,7 +193,7 @@ def run(arguments: ExplorerArguments) -> None: try: if arguments.generate_data_cu_inst is not None: # start generation of Data_CUInst and stop execution afterwards - from discopop_explorer.utilities.generate_Data_CUInst import wrapper as generate_data_cuinst_wrapper + from discopop_explorer.utilities.general.generate_Data_CUInst import wrapper as generate_data_cuinst_wrapper generate_data_cuinst_wrapper( arguments.cu_xml_file, diff --git a/discopop_explorer/utilities/general/__init__.py b/discopop_explorer/utilities/general/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/discopop_explorer/utilities/generate_Data_CUInst.py b/discopop_explorer/utilities/general/generate_Data_CUInst.py similarity index 100% rename from discopop_explorer/utilities/generate_Data_CUInst.py rename to discopop_explorer/utilities/general/generate_Data_CUInst.py From 115ed26019d1d3ef1e1dbce238c75bb8adda1b1a Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 31 Jul 2024 13:22:21 +0200 Subject: [PATCH 070/105] refactor: move --- discopop_explorer/classes/FunctionNode.py | 2 +- discopop_explorer/classes/LoopNode.py | 2 +- discopop_explorer/classes/{ => PEGraph}/PEGraphX.py | 0 discopop_explorer/classes/PEGraph/__init__.py | 0 discopop_explorer/classes/patterns/PatternInfo.py | 2 +- discopop_explorer/discopop_explorer.py | 2 +- discopop_explorer/parallel_utils.py | 2 +- discopop_explorer/pattern_detection.py | 2 +- .../combined_gpu_patterns/CombinedGPURegions.py | 2 +- .../combined_gpu_patterns/classes/EntryPoint.py | 2 +- .../combined_gpu_patterns/classes/ExitPoint.py | 2 +- .../pattern_detectors/combined_gpu_patterns/classes/Update.py | 2 +- .../combined_gpu_patterns/combined_gpu_pattern_detector.py | 2 +- .../pattern_detectors/combined_gpu_patterns/prepare_metadata.py | 2 +- .../pattern_detectors/combined_gpu_patterns/step_1.py | 2 +- .../pattern_detectors/combined_gpu_patterns/step_2.py | 2 +- .../pattern_detectors/combined_gpu_patterns/step_3.py | 2 +- .../pattern_detectors/combined_gpu_patterns/step_4.py | 2 +- .../pattern_detectors/combined_gpu_patterns/step_5.py | 2 +- .../pattern_detectors/combined_gpu_patterns/step_6.py | 2 +- .../pattern_detectors/combined_gpu_patterns/utilities.py | 2 +- discopop_explorer/pattern_detectors/device_updates.py | 2 +- discopop_explorer/pattern_detectors/do_all_detector.py | 2 +- .../pattern_detectors/geometric_decomposition_detector.py | 2 +- discopop_explorer/pattern_detectors/pipeline_detector.py | 2 +- discopop_explorer/pattern_detectors/reduction_detector.py | 2 +- .../pattern_detectors/simple_gpu_patterns/GPULoop.py | 2 +- .../pattern_detectors/simple_gpu_patterns/GPUMemory.py | 2 +- .../pattern_detectors/simple_gpu_patterns/GPURegions.py | 2 +- .../simple_gpu_patterns/gpu_pattern_detector.py | 2 +- discopop_explorer/pattern_detectors/task_parallelism/classes.py | 2 +- discopop_explorer/pattern_detectors/task_parallelism/filter.py | 2 +- .../pattern_detectors/task_parallelism/postprocessor.py | 2 +- .../pattern_detectors/task_parallelism/preprocessor.py | 2 +- .../pattern_detectors/task_parallelism/suggesters/auxiliary.py | 2 +- .../pattern_detectors/task_parallelism/suggesters/barriers.py | 2 +- .../task_parallelism/suggesters/data_sharing_clauses.py | 2 +- .../task_parallelism/suggesters/dependency_clauses.py | 2 +- .../pattern_detectors/task_parallelism/suggesters/tasks.py | 2 +- .../task_parallelism/task_parallelism_detector.py | 2 +- .../pattern_detectors/task_parallelism/tp_utils.py | 2 +- discopop_explorer/plugins/pipeline.py | 2 +- discopop_explorer/utilities/general/generate_Data_CUInst.py | 2 +- discopop_explorer/utils.py | 2 +- .../discopop_optimizer/PETParser/DataAccesses/FromCUs.py | 2 +- discopop_library/discopop_optimizer/PETParser/PETParser.py | 2 +- discopop_library/discopop_optimizer/classes/context/Update.py | 2 +- .../discopop_optimizer/gui/presentation/OptionTable.py | 2 +- discopop_library/result_classes/DetectionResult.py | 2 +- 49 files changed, 47 insertions(+), 47 deletions(-) rename discopop_explorer/classes/{ => PEGraph}/PEGraphX.py (100%) create mode 100644 discopop_explorer/classes/PEGraph/__init__.py diff --git a/discopop_explorer/classes/FunctionNode.py b/discopop_explorer/classes/FunctionNode.py index 3c6220444..71fb36b4d 100644 --- a/discopop_explorer/classes/FunctionNode.py +++ b/discopop_explorer/classes/FunctionNode.py @@ -21,7 +21,7 @@ from discopop_explorer.classes.variable import Variable if TYPE_CHECKING: - from discopop_explorer.classes.PEGraphX import PEGraphX + from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX # Data.xml: type="1" diff --git a/discopop_explorer/classes/LoopNode.py b/discopop_explorer/classes/LoopNode.py index 4d3fa7f57..ef29c103c 100644 --- a/discopop_explorer/classes/LoopNode.py +++ b/discopop_explorer/classes/LoopNode.py @@ -17,7 +17,7 @@ from discopop_explorer.utilities.PEGraphConstruction.classes.LoopData import LoopData if TYPE_CHECKING: - from discopop_explorer.classes.PEGraphX import PEGraphX + from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX # Data.xml: type="2" diff --git a/discopop_explorer/classes/PEGraphX.py b/discopop_explorer/classes/PEGraph/PEGraphX.py similarity index 100% rename from discopop_explorer/classes/PEGraphX.py rename to discopop_explorer/classes/PEGraph/PEGraphX.py diff --git a/discopop_explorer/classes/PEGraph/__init__.py b/discopop_explorer/classes/PEGraph/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/discopop_explorer/classes/patterns/PatternInfo.py b/discopop_explorer/classes/patterns/PatternInfo.py index 881d291a9..c87b8a259 100644 --- a/discopop_explorer/classes/patterns/PatternInfo.py +++ b/discopop_explorer/classes/patterns/PatternInfo.py @@ -10,7 +10,7 @@ from discopop_library.discopop_optimizer.classes.system.devices.DeviceTypeEnum import DeviceTypeEnum -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.classes.LoopNode import LoopNode from discopop_explorer.classes.Node import Node from discopop_explorer.utils import calculate_workload, calculate_per_iteration_workload_of_loop diff --git a/discopop_explorer/discopop_explorer.py b/discopop_explorer/discopop_explorer.py index 4a6ba0976..05ac53cc2 100644 --- a/discopop_explorer/discopop_explorer.py +++ b/discopop_explorer/discopop_explorer.py @@ -29,7 +29,7 @@ ExtrapInterpolatedMicrobench, ) from discopop_library.result_classes.DetectionResult import DetectionResult -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from .json_serializer import PatternBaseSerializer from discopop_explorer.utilities.PEGraphConstruction.parser import parse_inputs from .pattern_detection import PatternDetectorX diff --git a/discopop_explorer/parallel_utils.py b/discopop_explorer/parallel_utils.py index a49107ecf..b323f6cec 100644 --- a/discopop_explorer/parallel_utils.py +++ b/discopop_explorer/parallel_utils.py @@ -6,7 +6,7 @@ # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from .classes.FunctionNode import FunctionNode from .classes.Node import Node from .aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detection.py b/discopop_explorer/pattern_detection.py index f7f2d156b..905664e9c 100644 --- a/discopop_explorer/pattern_detection.py +++ b/discopop_explorer/pattern_detection.py @@ -20,7 +20,7 @@ from discopop_library.HostpotLoader.HotspotType import HotspotType from discopop_library.JSONHandler.JSONHandler import read_patterns_from_json_to_json from discopop_library.result_classes.DetectionResult import DetectionResult -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from .classes.DummyNode import DummyNode from .classes.LoopNode import LoopNode from .enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py index 98749b506..e7bb6977a 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py @@ -8,7 +8,7 @@ import sys from typing import List, Tuple, Dict, Set, cast -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py index 8bd8b7b11..b60a663ac 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py @@ -8,7 +8,7 @@ import os.path from typing import Set, Tuple, List -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py index 0d0c69a34..7ec36cc61 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py @@ -9,7 +9,7 @@ import os from typing import Set, List, Tuple -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py index 3f29a1c85..e5191c95a 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py @@ -9,7 +9,7 @@ import os from typing import Set, Dict, cast, Optional, List, Tuple -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.LineID import LineID from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/combined_gpu_pattern_detector.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/combined_gpu_pattern_detector.py index 842a3c12b..1c3634ab0 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/combined_gpu_pattern_detector.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/combined_gpu_pattern_detector.py @@ -8,7 +8,7 @@ from typing import List, cast -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.combined_gpu_patterns.CombinedGPURegions import ( find_combined_gpu_regions, diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/prepare_metadata.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/prepare_metadata.py index 65dee6804..3f5144d71 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/prepare_metadata.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/prepare_metadata.py @@ -8,7 +8,7 @@ from typing import Set, List, Tuple -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import VarName from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Dependency import Dependency diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py index 224925315..75cf08009 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py @@ -8,7 +8,7 @@ from typing import List, Tuple, Dict, Set, cast -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py index 55da7b6df..ee57718b4 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py @@ -11,7 +11,7 @@ import networkx as nx # type: ignore -from discopop_explorer.classes.PEGraphX import ( +from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) from discopop_explorer.classes.FunctionNode import FunctionNode diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py index e5bead1e1..432e8ee3f 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py @@ -8,7 +8,7 @@ from typing import Dict, List, Tuple, Set, Optional -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py index f39c259c8..fdce05cfc 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py @@ -13,7 +13,7 @@ import networkx as nx # type: ignore from networkx import NetworkXNoCycle, MultiDiGraph -from discopop_explorer.classes.PEGraphX import ( +from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) from discopop_explorer.classes.FunctionNode import FunctionNode diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_5.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_5.py index 21a9f7656..ea1d5d15b 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_5.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_5.py @@ -8,7 +8,7 @@ from typing import Dict, Set -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py index d388e2509..5baacc732 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py @@ -11,7 +11,7 @@ from networkx import MultiDiGraph # type: ignore -from discopop_explorer.classes.PEGraphX import ( +from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) from discopop_explorer.classes.FunctionNode import FunctionNode diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py index ff9a76c82..6721a531d 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py @@ -8,7 +8,7 @@ from typing import List, Set, Dict, Tuple, Optional -from discopop_explorer.classes.PEGraphX import ( +from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) from discopop_explorer.classes.FunctionNode import FunctionNode diff --git a/discopop_explorer/pattern_detectors/device_updates.py b/discopop_explorer/pattern_detectors/device_updates.py index 5d84caaad..314f745fe 100644 --- a/discopop_explorer/pattern_detectors/device_updates.py +++ b/discopop_explorer/pattern_detectors/device_updates.py @@ -8,7 +8,7 @@ from typing import Optional from discopop_explorer.classes.patterns.PatternInfo import PatternInfo -from discopop_explorer.classes.PEGraphX import ( +from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) from ..classes.Node import Node diff --git a/discopop_explorer/pattern_detectors/do_all_detector.py b/discopop_explorer/pattern_detectors/do_all_detector.py index a2dee40e1..8068ec12e 100644 --- a/discopop_explorer/pattern_detectors/do_all_detector.py +++ b/discopop_explorer/pattern_detectors/do_all_detector.py @@ -15,7 +15,7 @@ from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from .reduction_detector import ReductionInfo -from discopop_explorer.classes.PEGraphX import ( +from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) from ..classes.LoopNode import LoopNode diff --git a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py index e00c5a812..22cf0c6a1 100644 --- a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py +++ b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py @@ -15,7 +15,7 @@ from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore from discopop_explorer.classes.patterns.PatternInfo import PatternInfo -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from ..classes.FunctionNode import FunctionNode from ..classes.LoopNode import LoopNode from ..classes.Node import Node diff --git a/discopop_explorer/pattern_detectors/pipeline_detector.py b/discopop_explorer/pattern_detectors/pipeline_detector.py index 42161f0a4..db925fe8f 100644 --- a/discopop_explorer/pattern_detectors/pipeline_detector.py +++ b/discopop_explorer/pattern_detectors/pipeline_detector.py @@ -13,7 +13,7 @@ from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore from discopop_explorer.classes.patterns.PatternInfo import PatternInfo -from discopop_explorer.classes.PEGraphX import ( +from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) from ..classes.LoopNode import LoopNode diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index 0d43527cb..33ceab05d 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -15,7 +15,7 @@ from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore from discopop_explorer.classes.patterns.PatternInfo import PatternInfo -from discopop_explorer.classes.PEGraphX import ( +from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) from ..classes.LoopNode import LoopNode diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py index 39aa75460..0022c5689 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py @@ -9,7 +9,7 @@ from enum import IntEnum from typing import List, Set, Optional, Union, Any, Dict, Tuple, cast -from discopop_explorer.classes.PEGraphX import ( +from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) from ...classes.FunctionNode import FunctionNode diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py index 20362eb9c..d5e666cf4 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py @@ -9,7 +9,7 @@ from enum import Enum from typing import List, Set, cast, Tuple -from discopop_explorer.classes.PEGraphX import ( +from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) from discopop_explorer.classes.FunctionNode import FunctionNode diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py index 13a51462f..9ef283f95 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py @@ -10,7 +10,7 @@ from alive_progress import alive_bar # type: ignore -from discopop_explorer.classes.PEGraphX import ( +from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) from ...classes.LoopNode import LoopNode diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py index d86d33ae4..ed473497a 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py @@ -10,7 +10,7 @@ from alive_progress import alive_bar # type: ignore -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.classes.LoopNode import LoopNode from discopop_explorer.aliases.LineID import LineID from discopop_explorer.classes.patterns.PatternInfo import PatternInfo diff --git a/discopop_explorer/pattern_detectors/task_parallelism/classes.py b/discopop_explorer/pattern_detectors/task_parallelism/classes.py index c7480002d..73821020b 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/classes.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/classes.py @@ -9,7 +9,7 @@ from enum import Enum from typing import List, Optional -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.classes.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.MWType import MWType diff --git a/discopop_explorer/pattern_detectors/task_parallelism/filter.py b/discopop_explorer/pattern_detectors/task_parallelism/filter.py index 31f8c89e8..2fbe61c5b 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/filter.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/filter.py @@ -8,7 +8,7 @@ from typing import List, Dict, cast, Optional, Union -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.classes.Node import Node from discopop_explorer.enums.NodeType import NodeType diff --git a/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py b/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py index 9d6d84a6a..c221c1162 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py @@ -8,7 +8,7 @@ from typing import List, cast, Dict, Optional, Tuple -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.classes.Node import Node from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.classes.patterns.PatternInfo import PatternInfo diff --git a/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py b/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py index 12588a149..a1d6609e1 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py @@ -12,7 +12,7 @@ from lxml import objectify, etree # type: ignore -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.classes.LoopNode import LoopNode from discopop_explorer.pattern_detectors.task_parallelism.tp_utils import line_contained_in_region diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py index 731a35347..7f2a35d6b 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py @@ -9,7 +9,7 @@ import copy from typing import List, Tuple, Optional, cast, Dict -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.classes.Node import Node from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py index 4eeb80442..a32516225 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py @@ -8,7 +8,7 @@ from typing import List, cast, Tuple, Any -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.classes.Node import Node from discopop_explorer.aliases.LineID import LineID diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py index 32debfdaf..bb9990020 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py @@ -8,7 +8,7 @@ from typing import List -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.classes.FunctionNode import FunctionNode from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.classes.patterns.PatternInfo import PatternInfo diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py index efb085312..493ac70a0 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py @@ -9,7 +9,7 @@ import os from typing import List, Dict, Tuple, Optional, cast, Any -from discopop_explorer.classes.PEGraphX import ( +from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) from discopop_explorer.classes.FunctionNode import FunctionNode diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py index c1919b2a9..640b80a30 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py @@ -8,7 +8,7 @@ from typing import List, Dict, cast -from discopop_explorer.classes.PEGraphX import ( +from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) from discopop_explorer.classes.FunctionNode import FunctionNode diff --git a/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py b/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py index 820b99576..8f0e4be4f 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py @@ -9,7 +9,7 @@ from typing import Dict, List, Optional, Tuple, cast -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.classes.DummyNode import DummyNode from discopop_explorer.enums.MWType import MWType from discopop_explorer.utilities.PEGraphConstruction.parser import parse_inputs diff --git a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py index 9e8d2f007..95a6907ac 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py @@ -11,7 +11,7 @@ from lxml import objectify # type: ignore -from discopop_explorer.classes.PEGraphX import ( +from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) from discopop_explorer.classes.FunctionNode import FunctionNode diff --git a/discopop_explorer/plugins/pipeline.py b/discopop_explorer/plugins/pipeline.py index cda66a644..ce1558b94 100644 --- a/discopop_explorer/plugins/pipeline.py +++ b/discopop_explorer/plugins/pipeline.py @@ -9,7 +9,7 @@ from copy import deepcopy from typing import List -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from ..classes.LoopNode import LoopNode from ..classes.Node import Node from ..aliases.LineID import LineID diff --git a/discopop_explorer/utilities/general/generate_Data_CUInst.py b/discopop_explorer/utilities/general/generate_Data_CUInst.py index 6ce0b0c25..ec1fe433b 100644 --- a/discopop_explorer/utilities/general/generate_Data_CUInst.py +++ b/discopop_explorer/utilities/general/generate_Data_CUInst.py @@ -9,7 +9,7 @@ from io import TextIOWrapper from typing import List, cast, TextIO -from discopop_explorer.classes.PEGraphX import ( +from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) from discopop_explorer.classes.FunctionNode import FunctionNode diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index db21eb9d6..e9e78c677 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -31,7 +31,7 @@ from discopop_explorer.classes.variable import Variable if TYPE_CHECKING: - from discopop_explorer.classes.PEGraphX import PEGraphX + from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX loop_data: Dict[LineID, int] = {} diff --git a/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py b/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py index 31574f1b6..c8e392628 100644 --- a/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py +++ b/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py @@ -7,7 +7,7 @@ # directory for details. from typing import Tuple, Set, cast -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.classes.CUNode import CUNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_library/discopop_optimizer/PETParser/PETParser.py b/discopop_library/discopop_optimizer/PETParser/PETParser.py index c8fdc91f8..aea54928d 100644 --- a/discopop_library/discopop_optimizer/PETParser/PETParser.py +++ b/discopop_library/discopop_optimizer/PETParser/PETParser.py @@ -16,7 +16,7 @@ from sympy import Integer -from discopop_explorer.classes.PEGraphX import ( +from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) from discopop_explorer.classes.FunctionNode import FunctionNode diff --git a/discopop_library/discopop_optimizer/classes/context/Update.py b/discopop_library/discopop_optimizer/classes/context/Update.py index 186caf6ee..41265da7e 100644 --- a/discopop_library/discopop_optimizer/classes/context/Update.py +++ b/discopop_library/discopop_optimizer/classes/context/Update.py @@ -7,7 +7,7 @@ # directory for details. import json from typing import Any, Dict, Optional, Tuple, cast -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.aliases.NodeID import NodeID from discopop_library.discopop_optimizer.classes.types.Aliases import DeviceID from discopop_library.discopop_optimizer.classes.types.DataAccessType import ( diff --git a/discopop_library/discopop_optimizer/gui/presentation/OptionTable.py b/discopop_library/discopop_optimizer/gui/presentation/OptionTable.py index f0fc34c9a..fbadb97fb 100644 --- a/discopop_library/discopop_optimizer/gui/presentation/OptionTable.py +++ b/discopop_library/discopop_optimizer/gui/presentation/OptionTable.py @@ -12,7 +12,7 @@ import networkx as nx # type: ignore from sympy import Symbol -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.context.ContextObject import ContextObject diff --git a/discopop_library/result_classes/DetectionResult.py b/discopop_library/result_classes/DetectionResult.py index efa39fe0b..c69cdbd95 100644 --- a/discopop_library/result_classes/DetectionResult.py +++ b/discopop_library/result_classes/DetectionResult.py @@ -9,7 +9,7 @@ import jsonpickle # type: ignore -from discopop_explorer.classes.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_library.global_data.version.utils import get_version from discopop_library.result_classes.PatternStorage import PatternStorage From 2cd0a7526889f47e7d09a7dc692b26a33ec06892 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 31 Jul 2024 13:39:50 +0200 Subject: [PATCH 071/105] refactor: move --- discopop_explorer/classes/FunctionNode.py | 2 +- discopop_explorer/classes/{ => PEGraph}/CUNode.py | 0 discopop_explorer/classes/PEGraph/PEGraphX.py | 2 +- .../combined_gpu_patterns/CombinedGPURegions.py | 2 +- .../pattern_detectors/combined_gpu_patterns/step_1.py | 2 +- .../pattern_detectors/combined_gpu_patterns/step_2.py | 2 +- .../pattern_detectors/combined_gpu_patterns/step_3.py | 2 +- .../pattern_detectors/combined_gpu_patterns/step_4.py | 2 +- .../pattern_detectors/combined_gpu_patterns/step_6.py | 2 +- discopop_explorer/pattern_detectors/do_all_detector.py | 2 +- discopop_explorer/pattern_detectors/pipeline_detector.py | 2 +- discopop_explorer/pattern_detectors/reduction_detector.py | 2 +- .../pattern_detectors/simple_gpu_patterns/GPULoop.py | 2 +- .../pattern_detectors/simple_gpu_patterns/GPUMemory.py | 2 +- .../pattern_detectors/simple_gpu_patterns/GPURegions.py | 2 +- discopop_explorer/pattern_detectors/task_parallelism/filter.py | 2 +- .../pattern_detectors/task_parallelism/suggesters/barriers.py | 2 +- .../task_parallelism/suggesters/dependency_clauses.py | 2 +- .../pattern_detectors/task_parallelism/suggesters/tasks.py | 2 +- .../pattern_detectors/task_parallelism/tp_utils.py | 2 +- .../PEGraphConstruction/PEGraphConstructionUtilities.py | 2 +- discopop_explorer/utilities/general/generate_Data_CUInst.py | 2 +- discopop_explorer/utils.py | 2 +- .../discopop_optimizer/PETParser/DataAccesses/FromCUs.py | 2 +- discopop_library/discopop_optimizer/PETParser/PETParser.py | 2 +- 25 files changed, 24 insertions(+), 24 deletions(-) rename discopop_explorer/classes/{ => PEGraph}/CUNode.py (100%) diff --git a/discopop_explorer/classes/FunctionNode.py b/discopop_explorer/classes/FunctionNode.py index 71fb36b4d..9f23bf502 100644 --- a/discopop_explorer/classes/FunctionNode.py +++ b/discopop_explorer/classes/FunctionNode.py @@ -13,7 +13,7 @@ from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID -from discopop_explorer.classes.CUNode import CUNode +from discopop_explorer.classes.PEGraph.CUNode import CUNode from discopop_explorer.classes.Dependency import Dependency from discopop_explorer.classes.Node import Node from discopop_explorer.enums.EdgeType import EdgeType diff --git a/discopop_explorer/classes/CUNode.py b/discopop_explorer/classes/PEGraph/CUNode.py similarity index 100% rename from discopop_explorer/classes/CUNode.py rename to discopop_explorer/classes/PEGraph/CUNode.py diff --git a/discopop_explorer/classes/PEGraph/PEGraphX.py b/discopop_explorer/classes/PEGraph/PEGraphX.py index 56089c16a..8f19697d4 100644 --- a/discopop_explorer/classes/PEGraph/PEGraphX.py +++ b/discopop_explorer/classes/PEGraph/PEGraphX.py @@ -23,7 +23,7 @@ from discopop_explorer.aliases.LineID import LineID from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID -from discopop_explorer.classes.CUNode import CUNode +from discopop_explorer.classes.PEGraph.CUNode import CUNode from discopop_explorer.classes.Dependency import Dependency from discopop_explorer.classes.DummyNode import DummyNode from discopop_explorer.classes.FunctionNode import FunctionNode diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py index e7bb6977a..6bb5ad9f5 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py @@ -9,7 +9,7 @@ from typing import List, Tuple, Dict, Set, cast from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX -from discopop_explorer.classes.CUNode import CUNode +from discopop_explorer.classes.PEGraph.CUNode import CUNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py index 75cf08009..bf70e191a 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py @@ -9,7 +9,7 @@ from typing import List, Tuple, Dict, Set, cast from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX -from discopop_explorer.classes.CUNode import CUNode +from discopop_explorer.classes.PEGraph.CUNode import CUNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.DepType import DepType diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py index ee57718b4..038d54c9e 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py @@ -15,7 +15,7 @@ PEGraphX, ) from discopop_explorer.classes.FunctionNode import FunctionNode -from discopop_explorer.classes.CUNode import CUNode +from discopop_explorer.classes.PEGraph.CUNode import CUNode from discopop_explorer.classes.Dependency import Dependency from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py index 432e8ee3f..c46581d72 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py @@ -9,7 +9,7 @@ from typing import Dict, List, Tuple, Set, Optional from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX -from discopop_explorer.classes.CUNode import CUNode +from discopop_explorer.classes.PEGraph.CUNode import CUNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py index fdce05cfc..f802c544d 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py @@ -17,7 +17,7 @@ PEGraphX, ) from discopop_explorer.classes.FunctionNode import FunctionNode -from discopop_explorer.classes.CUNode import CUNode +from discopop_explorer.classes.PEGraph.CUNode import CUNode from discopop_explorer.classes.Dependency import Dependency from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py index 5baacc732..74b02b30f 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py @@ -15,7 +15,7 @@ PEGraphX, ) from discopop_explorer.classes.FunctionNode import FunctionNode -from discopop_explorer.classes.CUNode import CUNode +from discopop_explorer.classes.PEGraph.CUNode import CUNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.DepType import DepType diff --git a/discopop_explorer/pattern_detectors/do_all_detector.py b/discopop_explorer/pattern_detectors/do_all_detector.py index 8068ec12e..398b879fc 100644 --- a/discopop_explorer/pattern_detectors/do_all_detector.py +++ b/discopop_explorer/pattern_detectors/do_all_detector.py @@ -19,7 +19,7 @@ PEGraphX, ) from ..classes.LoopNode import LoopNode -from ..classes.CUNode import CUNode +from discopop_explorer.classes.PEGraph.CUNode import CUNode from ..classes.Node import Node from ..classes.Dependency import Dependency from ..aliases.MemoryRegion import MemoryRegion diff --git a/discopop_explorer/pattern_detectors/pipeline_detector.py b/discopop_explorer/pattern_detectors/pipeline_detector.py index db925fe8f..5e4c76ede 100644 --- a/discopop_explorer/pattern_detectors/pipeline_detector.py +++ b/discopop_explorer/pattern_detectors/pipeline_detector.py @@ -17,7 +17,7 @@ PEGraphX, ) from ..classes.LoopNode import LoopNode -from ..classes.CUNode import CUNode +from discopop_explorer.classes.PEGraph.CUNode import CUNode from ..classes.Node import Node from ..classes.Dependency import Dependency from ..aliases.LineID import LineID diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index 33ceab05d..72e9d9e83 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -19,7 +19,7 @@ PEGraphX, ) from ..classes.LoopNode import LoopNode -from ..classes.CUNode import CUNode +from discopop_explorer.classes.PEGraph.CUNode import CUNode from ..classes.Node import Node from ..classes.Dependency import Dependency from ..aliases.MemoryRegion import MemoryRegion diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py index 0022c5689..57599ae1a 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py @@ -14,7 +14,7 @@ ) from ...classes.FunctionNode import FunctionNode from ...classes.LoopNode import LoopNode -from ...classes.CUNode import CUNode +from discopop_explorer.classes.PEGraph.CUNode import CUNode from ...classes.Node import Node from ...aliases.MemoryRegion import MemoryRegion from ...aliases.LineID import LineID diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py index d5e666cf4..c5a75a85e 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py @@ -15,7 +15,7 @@ from discopop_explorer.classes.FunctionNode import FunctionNode from discopop_explorer.classes.DummyNode import DummyNode from discopop_explorer.classes.LoopNode import LoopNode -from discopop_explorer.classes.CUNode import CUNode +from discopop_explorer.classes.PEGraph.CUNode import CUNode from discopop_explorer.classes.Node import Node from discopop_explorer.classes.Dependency import Dependency from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py index 9ef283f95..2ced4df6e 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py @@ -14,7 +14,7 @@ PEGraphX, ) from ...classes.LoopNode import LoopNode -from ...classes.CUNode import CUNode +from discopop_explorer.classes.PEGraph.CUNode import CUNode from ...classes.Node import Node from ...aliases.NodeID import NodeID from ...enums.NodeType import NodeType diff --git a/discopop_explorer/pattern_detectors/task_parallelism/filter.py b/discopop_explorer/pattern_detectors/task_parallelism/filter.py index 2fbe61c5b..060f84d5f 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/filter.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/filter.py @@ -9,7 +9,7 @@ from typing import List, Dict, cast, Optional, Union from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX -from discopop_explorer.classes.CUNode import CUNode +from discopop_explorer.classes.PEGraph.CUNode import CUNode from discopop_explorer.classes.Node import Node from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py index a32516225..6d752a330 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py @@ -9,7 +9,7 @@ from typing import List, cast, Tuple, Any from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX -from discopop_explorer.classes.CUNode import CUNode +from discopop_explorer.classes.PEGraph.CUNode import CUNode from discopop_explorer.classes.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.NodeType import NodeType diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py index 493ac70a0..b9b07f6ce 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py @@ -13,7 +13,7 @@ PEGraphX, ) from discopop_explorer.classes.FunctionNode import FunctionNode -from discopop_explorer.classes.CUNode import CUNode +from discopop_explorer.classes.PEGraph.CUNode import CUNode from discopop_explorer.classes.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py index 640b80a30..95f236ad4 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py @@ -13,7 +13,7 @@ ) from discopop_explorer.classes.FunctionNode import FunctionNode from discopop_explorer.classes.LoopNode import LoopNode -from discopop_explorer.classes.CUNode import CUNode +from discopop_explorer.classes.PEGraph.CUNode import CUNode from discopop_explorer.classes.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.MWType import MWType diff --git a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py index 95a6907ac..619924b67 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py @@ -16,7 +16,7 @@ ) from discopop_explorer.classes.FunctionNode import FunctionNode from discopop_explorer.classes.DummyNode import DummyNode -from discopop_explorer.classes.CUNode import CUNode +from discopop_explorer.classes.PEGraph.CUNode import CUNode from discopop_explorer.classes.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.NodeType import NodeType diff --git a/discopop_explorer/utilities/PEGraphConstruction/PEGraphConstructionUtilities.py b/discopop_explorer/utilities/PEGraphConstruction/PEGraphConstructionUtilities.py index 741a500cc..2f1b0aa2e 100644 --- a/discopop_explorer/utilities/PEGraphConstruction/PEGraphConstructionUtilities.py +++ b/discopop_explorer/utilities/PEGraphConstruction/PEGraphConstructionUtilities.py @@ -12,7 +12,7 @@ from lxml.objectify import ObjectifiedElement # type: ignore -from discopop_explorer.classes.CUNode import CUNode +from discopop_explorer.classes.PEGraph.CUNode import CUNode from discopop_explorer.classes.Dependency import Dependency from discopop_explorer.classes.DummyNode import DummyNode diff --git a/discopop_explorer/utilities/general/generate_Data_CUInst.py b/discopop_explorer/utilities/general/generate_Data_CUInst.py index ec1fe433b..66a4cff83 100644 --- a/discopop_explorer/utilities/general/generate_Data_CUInst.py +++ b/discopop_explorer/utilities/general/generate_Data_CUInst.py @@ -14,7 +14,7 @@ ) from discopop_explorer.classes.FunctionNode import FunctionNode from discopop_explorer.classes.LoopNode import LoopNode -from discopop_explorer.classes.CUNode import CUNode +from discopop_explorer.classes.PEGraph.CUNode import CUNode from discopop_explorer.classes.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index e9e78c677..05937b46b 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -18,7 +18,7 @@ from discopop_explorer.classes.FunctionNode import FunctionNode from discopop_explorer.classes.LoopNode import LoopNode -from discopop_explorer.classes.CUNode import CUNode +from discopop_explorer.classes.PEGraph.CUNode import CUNode from discopop_explorer.classes.Node import Node from discopop_explorer.classes.Dependency import Dependency from discopop_explorer.aliases.MemoryRegion import MemoryRegion diff --git a/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py b/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py index c8e392628..3520f8011 100644 --- a/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py +++ b/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py @@ -8,7 +8,7 @@ from typing import Tuple, Set, cast from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX -from discopop_explorer.classes.CUNode import CUNode +from discopop_explorer.classes.PEGraph.CUNode import CUNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.DepType import DepType diff --git a/discopop_library/discopop_optimizer/PETParser/PETParser.py b/discopop_library/discopop_optimizer/PETParser/PETParser.py index aea54928d..87a6d00b0 100644 --- a/discopop_library/discopop_optimizer/PETParser/PETParser.py +++ b/discopop_library/discopop_optimizer/PETParser/PETParser.py @@ -21,7 +21,7 @@ ) from discopop_explorer.classes.FunctionNode import FunctionNode from discopop_explorer.classes.LoopNode import LoopNode -from discopop_explorer.classes.CUNode import CUNode +from discopop_explorer.classes.PEGraph.CUNode import CUNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType From 38a2f383b2beaf784f9c8471f90227802e338cf9 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 31 Jul 2024 13:49:22 +0200 Subject: [PATCH 072/105] refactor: move --- discopop_explorer/classes/PEGraph/CUNode.py | 2 +- discopop_explorer/classes/{ => PEGraph}/Dependency.py | 0 discopop_explorer/classes/{ => PEGraph}/DummyNode.py | 2 +- .../classes/{ => PEGraph}/FunctionNode.py | 4 ++-- discopop_explorer/classes/{ => PEGraph}/LoopNode.py | 4 ++-- discopop_explorer/classes/{ => PEGraph}/Node.py | 0 discopop_explorer/classes/PEGraph/PEGraphX.py | 10 +++++----- discopop_explorer/classes/patterns/PatternBase.py | 2 +- discopop_explorer/classes/patterns/PatternInfo.py | 4 ++-- discopop_explorer/json_serializer.py | 2 +- discopop_explorer/parallel_utils.py | 4 ++-- discopop_explorer/pattern_detection.py | 4 ++-- .../pattern_detectors/combined_gpu_patterns/step_2.py | 4 ++-- .../pattern_detectors/combined_gpu_patterns/step_4.py | 4 ++-- .../pattern_detectors/combined_gpu_patterns/step_6.py | 2 +- .../combined_gpu_patterns/utilities.py | 2 +- discopop_explorer/pattern_detectors/device_updates.py | 2 +- discopop_explorer/pattern_detectors/do_all_detector.py | 6 +++--- .../geometric_decomposition_detector.py | 6 +++--- .../pattern_detectors/pipeline_detector.py | 6 +++--- .../pattern_detectors/reduction_detector.py | 6 +++--- .../pattern_detectors/simple_gpu_patterns/GPULoop.py | 6 +++--- .../pattern_detectors/simple_gpu_patterns/GPUMemory.py | 10 +++++----- .../simple_gpu_patterns/GPURegions.py | 4 ++-- .../simple_gpu_patterns/gpu_pattern_detector.py | 2 +- .../task_parallelism/alias_detection.py | 2 -- .../pattern_detectors/task_parallelism/classes.py | 2 +- .../pattern_detectors/task_parallelism/filter.py | 2 +- .../task_parallelism/postprocessor.py | 2 +- .../pattern_detectors/task_parallelism/preprocessor.py | 2 +- .../task_parallelism/suggesters/auxiliary.py | 2 +- .../task_parallelism/suggesters/barriers.py | 2 +- .../suggesters/data_sharing_clauses.py | 2 +- .../task_parallelism/suggesters/dependency_clauses.py | 4 ++-- .../task_parallelism/suggesters/tasks.py | 6 +++--- .../task_parallelism/task_parallelism_detector.py | 2 +- .../pattern_detectors/task_parallelism/tp_utils.py | 6 +++--- discopop_explorer/plugins/pipeline.py | 4 ++-- .../PEGraphConstructionUtilities.py | 10 +++++----- .../utilities/general/generate_Data_CUInst.py | 6 +++--- discopop_explorer/utils.py | 8 ++++---- discopop_library/EmpiricalAutotuning/Autotuner.py | 4 ++-- .../discopop_optimizer/PETParser/PETParser.py | 4 ++-- .../UpdateOptimization/RemoveLoopIndexUpdates.py | 2 +- discopop_library/result_classes/MergedPattern.py | 2 +- .../result_classes/OptimizerOutputPattern.py | 2 +- 46 files changed, 86 insertions(+), 88 deletions(-) rename discopop_explorer/classes/{ => PEGraph}/Dependency.py (100%) rename discopop_explorer/classes/{ => PEGraph}/DummyNode.py (92%) rename discopop_explorer/classes/{ => PEGraph}/FunctionNode.py (98%) rename discopop_explorer/classes/{ => PEGraph}/LoopNode.py (96%) rename discopop_explorer/classes/{ => PEGraph}/Node.py (100%) diff --git a/discopop_explorer/classes/PEGraph/CUNode.py b/discopop_explorer/classes/PEGraph/CUNode.py index 11b9e0b42..799fcf8f6 100644 --- a/discopop_explorer/classes/PEGraph/CUNode.py +++ b/discopop_explorer/classes/PEGraph/CUNode.py @@ -9,7 +9,7 @@ from typing import TYPE_CHECKING, List -from discopop_explorer.classes.Node import Node +from discopop_explorer.classes.PEGraph.Node import Node from discopop_explorer.enums.NodeType import NodeType if TYPE_CHECKING: diff --git a/discopop_explorer/classes/Dependency.py b/discopop_explorer/classes/PEGraph/Dependency.py similarity index 100% rename from discopop_explorer/classes/Dependency.py rename to discopop_explorer/classes/PEGraph/Dependency.py diff --git a/discopop_explorer/classes/DummyNode.py b/discopop_explorer/classes/PEGraph/DummyNode.py similarity index 92% rename from discopop_explorer/classes/DummyNode.py rename to discopop_explorer/classes/PEGraph/DummyNode.py index 2ca58118b..c56010f46 100644 --- a/discopop_explorer/classes/DummyNode.py +++ b/discopop_explorer/classes/PEGraph/DummyNode.py @@ -10,7 +10,7 @@ from typing import List from discopop_explorer.aliases.NodeID import NodeID -from discopop_explorer.classes.Node import Node +from discopop_explorer.classes.PEGraph.Node import Node from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.classes.variable import Variable diff --git a/discopop_explorer/classes/FunctionNode.py b/discopop_explorer/classes/PEGraph/FunctionNode.py similarity index 98% rename from discopop_explorer/classes/FunctionNode.py rename to discopop_explorer/classes/PEGraph/FunctionNode.py index 9f23bf502..d95d07ef7 100644 --- a/discopop_explorer/classes/FunctionNode.py +++ b/discopop_explorer/classes/PEGraph/FunctionNode.py @@ -14,8 +14,8 @@ from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.classes.PEGraph.CUNode import CUNode -from discopop_explorer.classes.Dependency import Dependency -from discopop_explorer.classes.Node import Node +from discopop_explorer.classes.PEGraph.Dependency import Dependency +from discopop_explorer.classes.PEGraph.Node import Node from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.classes.variable import Variable diff --git a/discopop_explorer/classes/LoopNode.py b/discopop_explorer/classes/PEGraph/LoopNode.py similarity index 96% rename from discopop_explorer/classes/LoopNode.py rename to discopop_explorer/classes/PEGraph/LoopNode.py index ef29c103c..c547a3709 100644 --- a/discopop_explorer/classes/LoopNode.py +++ b/discopop_explorer/classes/PEGraph/LoopNode.py @@ -9,9 +9,9 @@ from typing import TYPE_CHECKING, Optional, List -from discopop_explorer.classes.FunctionNode import FunctionNode +from discopop_explorer.classes.PEGraph.FunctionNode import FunctionNode from discopop_explorer.aliases.NodeID import NodeID -from discopop_explorer.classes.Node import Node +from discopop_explorer.classes.PEGraph.Node import Node from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.utilities.PEGraphConstruction.classes.LoopData import LoopData diff --git a/discopop_explorer/classes/Node.py b/discopop_explorer/classes/PEGraph/Node.py similarity index 100% rename from discopop_explorer/classes/Node.py rename to discopop_explorer/classes/PEGraph/Node.py diff --git a/discopop_explorer/classes/PEGraph/PEGraphX.py b/discopop_explorer/classes/PEGraph/PEGraphX.py index 8f19697d4..0f4af1a3d 100644 --- a/discopop_explorer/classes/PEGraph/PEGraphX.py +++ b/discopop_explorer/classes/PEGraph/PEGraphX.py @@ -24,11 +24,11 @@ from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.classes.PEGraph.CUNode import CUNode -from discopop_explorer.classes.Dependency import Dependency -from discopop_explorer.classes.DummyNode import DummyNode -from discopop_explorer.classes.FunctionNode import FunctionNode -from discopop_explorer.classes.LoopNode import LoopNode -from discopop_explorer.classes.Node import Node +from discopop_explorer.classes.PEGraph.Dependency import Dependency +from discopop_explorer.classes.PEGraph.DummyNode import DummyNode +from discopop_explorer.classes.PEGraph.FunctionNode import FunctionNode +from discopop_explorer.classes.PEGraph.LoopNode import LoopNode +from discopop_explorer.classes.PEGraph.Node import Node from discopop_explorer.enums.DepType import DepType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.enums.NodeType import NodeType diff --git a/discopop_explorer/classes/patterns/PatternBase.py b/discopop_explorer/classes/patterns/PatternBase.py index ae0173ea9..39e4c59b8 100644 --- a/discopop_explorer/classes/patterns/PatternBase.py +++ b/discopop_explorer/classes/patterns/PatternBase.py @@ -10,7 +10,7 @@ import os from filelock import FileLock # type: ignore -from discopop_explorer.classes.Node import Node +from discopop_explorer.classes.PEGraph.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_explorer/classes/patterns/PatternInfo.py b/discopop_explorer/classes/patterns/PatternInfo.py index c87b8a259..875a0f8f4 100644 --- a/discopop_explorer/classes/patterns/PatternInfo.py +++ b/discopop_explorer/classes/patterns/PatternInfo.py @@ -11,8 +11,8 @@ from discopop_library.discopop_optimizer.classes.system.devices.DeviceTypeEnum import DeviceTypeEnum from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX -from discopop_explorer.classes.LoopNode import LoopNode -from discopop_explorer.classes.Node import Node +from discopop_explorer.classes.PEGraph.LoopNode import LoopNode +from discopop_explorer.classes.PEGraph.Node import Node from discopop_explorer.utils import calculate_workload, calculate_per_iteration_workload_of_loop diff --git a/discopop_explorer/json_serializer.py b/discopop_explorer/json_serializer.py index 4f644ed82..d402f5234 100644 --- a/discopop_explorer/json_serializer.py +++ b/discopop_explorer/json_serializer.py @@ -14,7 +14,7 @@ from discopop_library.result_classes.DetectionResult import DetectionResult from discopop_library.result_classes.PatternStorage import PatternStorage -from .classes.Node import Node +from discopop_explorer.classes.PEGraph.Node import Node from .pattern_detectors.pipeline_detector import PipelineStage from .pattern_detectors.task_parallelism.classes import TPIType from .classes.variable import Variable diff --git a/discopop_explorer/parallel_utils.py b/discopop_explorer/parallel_utils.py index b323f6cec..9d4ea540f 100644 --- a/discopop_explorer/parallel_utils.py +++ b/discopop_explorer/parallel_utils.py @@ -7,8 +7,8 @@ # directory for details. from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX -from .classes.FunctionNode import FunctionNode -from .classes.Node import Node +from discopop_explorer.classes.PEGraph.FunctionNode import FunctionNode +from discopop_explorer.classes.PEGraph.Node import Node from .aliases.NodeID import NodeID from typing import Any, List, Optional, Set, Tuple diff --git a/discopop_explorer/pattern_detection.py b/discopop_explorer/pattern_detection.py index 905664e9c..40fd7979d 100644 --- a/discopop_explorer/pattern_detection.py +++ b/discopop_explorer/pattern_detection.py @@ -21,8 +21,8 @@ from discopop_library.JSONHandler.JSONHandler import read_patterns_from_json_to_json from discopop_library.result_classes.DetectionResult import DetectionResult from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX -from .classes.DummyNode import DummyNode -from .classes.LoopNode import LoopNode +from discopop_explorer.classes.PEGraph.DummyNode import DummyNode +from discopop_explorer.classes.PEGraph.LoopNode import LoopNode from .enums.EdgeType import EdgeType from .pattern_detectors.do_all_detector import DoAllInfo, run_detection as detect_do_all from .pattern_detectors.geometric_decomposition_detector import run_detection as detect_gd diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py index 038d54c9e..5cb8eee59 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py @@ -14,9 +14,9 @@ from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) -from discopop_explorer.classes.FunctionNode import FunctionNode +from discopop_explorer.classes.PEGraph.FunctionNode import FunctionNode from discopop_explorer.classes.PEGraph.CUNode import CUNode -from discopop_explorer.classes.Dependency import Dependency +from discopop_explorer.classes.PEGraph.Dependency import Dependency from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.NodeType import NodeType diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py index f802c544d..9e08dfc4a 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py @@ -16,9 +16,9 @@ from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) -from discopop_explorer.classes.FunctionNode import FunctionNode +from discopop_explorer.classes.PEGraph.FunctionNode import FunctionNode from discopop_explorer.classes.PEGraph.CUNode import CUNode -from discopop_explorer.classes.Dependency import Dependency +from discopop_explorer.classes.PEGraph.Dependency import Dependency from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.NodeType import NodeType diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py index 74b02b30f..e6d751d62 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py @@ -14,7 +14,7 @@ from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) -from discopop_explorer.classes.FunctionNode import FunctionNode +from discopop_explorer.classes.PEGraph.FunctionNode import FunctionNode from discopop_explorer.classes.PEGraph.CUNode import CUNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py index 6721a531d..0c4b416ec 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py @@ -11,7 +11,7 @@ from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) -from discopop_explorer.classes.FunctionNode import FunctionNode +from discopop_explorer.classes.PEGraph.FunctionNode import FunctionNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/device_updates.py b/discopop_explorer/pattern_detectors/device_updates.py index 314f745fe..ff0e020b9 100644 --- a/discopop_explorer/pattern_detectors/device_updates.py +++ b/discopop_explorer/pattern_detectors/device_updates.py @@ -11,7 +11,7 @@ from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) -from ..classes.Node import Node +from discopop_explorer.classes.PEGraph.Node import Node from ..aliases.MemoryRegion import MemoryRegion from ..aliases.LineID import LineID diff --git a/discopop_explorer/pattern_detectors/do_all_detector.py b/discopop_explorer/pattern_detectors/do_all_detector.py index 398b879fc..6b40ecb21 100644 --- a/discopop_explorer/pattern_detectors/do_all_detector.py +++ b/discopop_explorer/pattern_detectors/do_all_detector.py @@ -18,10 +18,10 @@ from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) -from ..classes.LoopNode import LoopNode +from discopop_explorer.classes.PEGraph.LoopNode import LoopNode from discopop_explorer.classes.PEGraph.CUNode import CUNode -from ..classes.Node import Node -from ..classes.Dependency import Dependency +from discopop_explorer.classes.PEGraph.Node import Node +from discopop_explorer.classes.PEGraph.Dependency import Dependency from ..aliases.MemoryRegion import MemoryRegion from ..aliases.LineID import LineID from ..aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py index 22cf0c6a1..a664e8d35 100644 --- a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py +++ b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py @@ -16,9 +16,9 @@ from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX -from ..classes.FunctionNode import FunctionNode -from ..classes.LoopNode import LoopNode -from ..classes.Node import Node +from discopop_explorer.classes.PEGraph.FunctionNode import FunctionNode +from discopop_explorer.classes.PEGraph.LoopNode import LoopNode +from discopop_explorer.classes.PEGraph.Node import Node from ..aliases.NodeID import NodeID from ..enums.EdgeType import EdgeType from ..utils import classify_task_vars, filter_for_hotspots, get_child_loops diff --git a/discopop_explorer/pattern_detectors/pipeline_detector.py b/discopop_explorer/pattern_detectors/pipeline_detector.py index 5e4c76ede..191438f4e 100644 --- a/discopop_explorer/pattern_detectors/pipeline_detector.py +++ b/discopop_explorer/pattern_detectors/pipeline_detector.py @@ -16,10 +16,10 @@ from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) -from ..classes.LoopNode import LoopNode +from discopop_explorer.classes.PEGraph.LoopNode import LoopNode from discopop_explorer.classes.PEGraph.CUNode import CUNode -from ..classes.Node import Node -from ..classes.Dependency import Dependency +from discopop_explorer.classes.PEGraph.Node import Node +from discopop_explorer.classes.PEGraph.Dependency import Dependency from ..aliases.LineID import LineID from ..aliases.NodeID import NodeID from ..enums.DepType import DepType diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index 72e9d9e83..5a27081c8 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -18,10 +18,10 @@ from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) -from ..classes.LoopNode import LoopNode +from discopop_explorer.classes.PEGraph.LoopNode import LoopNode from discopop_explorer.classes.PEGraph.CUNode import CUNode -from ..classes.Node import Node -from ..classes.Dependency import Dependency +from discopop_explorer.classes.PEGraph.Node import Node +from discopop_explorer.classes.PEGraph.Dependency import Dependency from ..aliases.MemoryRegion import MemoryRegion from ..aliases.LineID import LineID from ..aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py index 57599ae1a..b7ac848ea 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py @@ -12,10 +12,10 @@ from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) -from ...classes.FunctionNode import FunctionNode -from ...classes.LoopNode import LoopNode +from discopop_explorer.classes.PEGraph.FunctionNode import FunctionNode +from discopop_explorer.classes.PEGraph.LoopNode import LoopNode from discopop_explorer.classes.PEGraph.CUNode import CUNode -from ...classes.Node import Node +from discopop_explorer.classes.PEGraph.Node import Node from ...aliases.MemoryRegion import MemoryRegion from ...aliases.LineID import LineID from ...aliases.NodeID import NodeID diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py index c5a75a85e..8775f2781 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py @@ -12,12 +12,12 @@ from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) -from discopop_explorer.classes.FunctionNode import FunctionNode -from discopop_explorer.classes.DummyNode import DummyNode -from discopop_explorer.classes.LoopNode import LoopNode +from discopop_explorer.classes.PEGraph.FunctionNode import FunctionNode +from discopop_explorer.classes.PEGraph.DummyNode import DummyNode +from discopop_explorer.classes.PEGraph.LoopNode import LoopNode from discopop_explorer.classes.PEGraph.CUNode import CUNode -from discopop_explorer.classes.Node import Node -from discopop_explorer.classes.Dependency import Dependency +from discopop_explorer.classes.PEGraph.Node import Node +from discopop_explorer.classes.PEGraph.Dependency import Dependency from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.DepType import DepType from discopop_explorer.utils import is_func_arg, is_global, __get_dep_of_type as get_dep_of_type diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py index 2ced4df6e..6ebfb3d2c 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py @@ -13,9 +13,9 @@ from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) -from ...classes.LoopNode import LoopNode +from discopop_explorer.classes.PEGraph.LoopNode import LoopNode from discopop_explorer.classes.PEGraph.CUNode import CUNode -from ...classes.Node import Node +from discopop_explorer.classes.PEGraph.Node import Node from ...aliases.NodeID import NodeID from ...enums.NodeType import NodeType from ...enums.DepType import DepType diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py index ed473497a..0c70288fe 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py @@ -11,7 +11,7 @@ from alive_progress import alive_bar # type: ignore from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX -from discopop_explorer.classes.LoopNode import LoopNode +from discopop_explorer.classes.PEGraph.LoopNode import LoopNode from discopop_explorer.aliases.LineID import LineID from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.simple_gpu_patterns.GPULoop import GPULoopPattern diff --git a/discopop_explorer/pattern_detectors/task_parallelism/alias_detection.py b/discopop_explorer/pattern_detectors/task_parallelism/alias_detection.py index ae1d729f2..736796c80 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/alias_detection.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/alias_detection.py @@ -14,8 +14,6 @@ from lxml import objectify # type: ignore -import discopop_explorer.classes.Node - def __prune_statement(stmt_copy: str, statement: str, var_name: str, var_type: str) -> Optional[List[str]]: """splits a statement and performs multiple alias analyses if necessary (more than one '=' contained diff --git a/discopop_explorer/pattern_detectors/task_parallelism/classes.py b/discopop_explorer/pattern_detectors/task_parallelism/classes.py index 73821020b..8b4734499 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/classes.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/classes.py @@ -10,7 +10,7 @@ from typing import List, Optional from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX -from discopop_explorer.classes.Node import Node +from discopop_explorer.classes.PEGraph.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.MWType import MWType from discopop_explorer.classes.patterns.PatternInfo import PatternInfo diff --git a/discopop_explorer/pattern_detectors/task_parallelism/filter.py b/discopop_explorer/pattern_detectors/task_parallelism/filter.py index 060f84d5f..9d283f46d 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/filter.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/filter.py @@ -10,7 +10,7 @@ from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.classes.PEGraph.CUNode import CUNode -from discopop_explorer.classes.Node import Node +from discopop_explorer.classes.PEGraph.Node import Node from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.classes.patterns.PatternInfo import PatternInfo diff --git a/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py b/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py index c221c1162..ea74059e4 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py @@ -9,7 +9,7 @@ from typing import List, cast, Dict, Optional, Tuple from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX -from discopop_explorer.classes.Node import Node +from discopop_explorer.classes.PEGraph.Node import Node from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.task_parallelism.classes import ( diff --git a/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py b/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py index a1d6609e1..8077060e0 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py @@ -13,7 +13,7 @@ from lxml import objectify, etree # type: ignore from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX -from discopop_explorer.classes.LoopNode import LoopNode +from discopop_explorer.classes.PEGraph.LoopNode import LoopNode from discopop_explorer.pattern_detectors.task_parallelism.tp_utils import line_contained_in_region diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py index 7f2a35d6b..97d05d07c 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py @@ -10,7 +10,7 @@ from typing import List, Tuple, Optional, cast, Dict from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX -from discopop_explorer.classes.Node import Node +from discopop_explorer.classes.PEGraph.Node import Node from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.classes.patterns.PatternInfo import PatternInfo diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py index 6d752a330..10ed929cb 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py @@ -10,7 +10,7 @@ from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.classes.PEGraph.CUNode import CUNode -from discopop_explorer.classes.Node import Node +from discopop_explorer.classes.PEGraph.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py index bb9990020..5490b9f48 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py @@ -9,7 +9,7 @@ from typing import List from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX -from discopop_explorer.classes.FunctionNode import FunctionNode +from discopop_explorer.classes.PEGraph.FunctionNode import FunctionNode from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.task_parallelism.classes import ( diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py index b9b07f6ce..88ebde17e 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py @@ -12,9 +12,9 @@ from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) -from discopop_explorer.classes.FunctionNode import FunctionNode +from discopop_explorer.classes.PEGraph.FunctionNode import FunctionNode from discopop_explorer.classes.PEGraph.CUNode import CUNode -from discopop_explorer.classes.Node import Node +from discopop_explorer.classes.PEGraph.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py index 95f236ad4..d701c76d9 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py @@ -11,10 +11,10 @@ from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) -from discopop_explorer.classes.FunctionNode import FunctionNode -from discopop_explorer.classes.LoopNode import LoopNode +from discopop_explorer.classes.PEGraph.FunctionNode import FunctionNode +from discopop_explorer.classes.PEGraph.LoopNode import LoopNode from discopop_explorer.classes.PEGraph.CUNode import CUNode -from discopop_explorer.classes.Node import Node +from discopop_explorer.classes.PEGraph.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.MWType import MWType from discopop_explorer.enums.EdgeType import EdgeType diff --git a/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py b/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py index 8f0e4be4f..7a11c679a 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py @@ -10,7 +10,7 @@ from typing import Dict, List, Optional, Tuple, cast from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX -from discopop_explorer.classes.DummyNode import DummyNode +from discopop_explorer.classes.PEGraph.DummyNode import DummyNode from discopop_explorer.enums.MWType import MWType from discopop_explorer.utilities.PEGraphConstruction.parser import parse_inputs from discopop_explorer.classes.patterns.PatternInfo import PatternInfo diff --git a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py index 619924b67..0269f8a75 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py @@ -14,10 +14,10 @@ from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) -from discopop_explorer.classes.FunctionNode import FunctionNode -from discopop_explorer.classes.DummyNode import DummyNode +from discopop_explorer.classes.PEGraph.FunctionNode import FunctionNode +from discopop_explorer.classes.PEGraph.DummyNode import DummyNode from discopop_explorer.classes.PEGraph.CUNode import CUNode -from discopop_explorer.classes.Node import Node +from discopop_explorer.classes.PEGraph.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.MWType import MWType diff --git a/discopop_explorer/plugins/pipeline.py b/discopop_explorer/plugins/pipeline.py index ce1558b94..936676030 100644 --- a/discopop_explorer/plugins/pipeline.py +++ b/discopop_explorer/plugins/pipeline.py @@ -10,8 +10,8 @@ from typing import List from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX -from ..classes.LoopNode import LoopNode -from ..classes.Node import Node +from discopop_explorer.classes.PEGraph.LoopNode import LoopNode +from discopop_explorer.classes.PEGraph.Node import Node from ..aliases.LineID import LineID from ..enums.EdgeType import EdgeType from ..utils import correlation_coefficient diff --git a/discopop_explorer/utilities/PEGraphConstruction/PEGraphConstructionUtilities.py b/discopop_explorer/utilities/PEGraphConstruction/PEGraphConstructionUtilities.py index 2f1b0aa2e..b3dc60666 100644 --- a/discopop_explorer/utilities/PEGraphConstruction/PEGraphConstructionUtilities.py +++ b/discopop_explorer/utilities/PEGraphConstruction/PEGraphConstructionUtilities.py @@ -14,11 +14,11 @@ from discopop_explorer.classes.PEGraph.CUNode import CUNode -from discopop_explorer.classes.Dependency import Dependency -from discopop_explorer.classes.DummyNode import DummyNode -from discopop_explorer.classes.FunctionNode import FunctionNode -from discopop_explorer.classes.LoopNode import LoopNode -from discopop_explorer.classes.Node import Node +from discopop_explorer.classes.PEGraph.Dependency import Dependency +from discopop_explorer.classes.PEGraph.DummyNode import DummyNode +from discopop_explorer.classes.PEGraph.FunctionNode import FunctionNode +from discopop_explorer.classes.PEGraph.LoopNode import LoopNode +from discopop_explorer.classes.PEGraph.Node import Node from discopop_explorer.enums.DepType import DepType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.enums.NodeType import NodeType diff --git a/discopop_explorer/utilities/general/generate_Data_CUInst.py b/discopop_explorer/utilities/general/generate_Data_CUInst.py index 66a4cff83..dbfbb38da 100644 --- a/discopop_explorer/utilities/general/generate_Data_CUInst.py +++ b/discopop_explorer/utilities/general/generate_Data_CUInst.py @@ -12,10 +12,10 @@ from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) -from discopop_explorer.classes.FunctionNode import FunctionNode -from discopop_explorer.classes.LoopNode import LoopNode +from discopop_explorer.classes.PEGraph.FunctionNode import FunctionNode +from discopop_explorer.classes.PEGraph.LoopNode import LoopNode from discopop_explorer.classes.PEGraph.CUNode import CUNode -from discopop_explorer.classes.Node import Node +from discopop_explorer.classes.PEGraph.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.DepType import DepType diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index 05937b46b..88c6a5373 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -16,11 +16,11 @@ from discopop_library.HostpotLoader.HotspotType import HotspotType -from discopop_explorer.classes.FunctionNode import FunctionNode -from discopop_explorer.classes.LoopNode import LoopNode +from discopop_explorer.classes.PEGraph.FunctionNode import FunctionNode +from discopop_explorer.classes.PEGraph.LoopNode import LoopNode from discopop_explorer.classes.PEGraph.CUNode import CUNode -from discopop_explorer.classes.Node import Node -from discopop_explorer.classes.Dependency import Dependency +from discopop_explorer.classes.PEGraph.Node import Node +from discopop_explorer.classes.PEGraph.Dependency import Dependency from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.LineID import LineID from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_library/EmpiricalAutotuning/Autotuner.py b/discopop_library/EmpiricalAutotuning/Autotuner.py index 624522ace..96e738dd8 100644 --- a/discopop_library/EmpiricalAutotuning/Autotuner.py +++ b/discopop_library/EmpiricalAutotuning/Autotuner.py @@ -8,10 +8,10 @@ import logging import os -from typing import List, Optional, Set, Tuple, cast +from typing import List, Tuple, cast import jsonpickle # type: ignore -from discopop_explorer.classes.LoopNode import LoopNode +from discopop_explorer.classes.PEGraph.LoopNode import LoopNode from discopop_library.EmpiricalAutotuning.ArgumentClasses import AutotunerArguments from discopop_library.EmpiricalAutotuning.Classes.CodeConfiguration import CodeConfiguration from discopop_library.EmpiricalAutotuning.Classes.ExecutionResult import ExecutionResult diff --git a/discopop_library/discopop_optimizer/PETParser/PETParser.py b/discopop_library/discopop_optimizer/PETParser/PETParser.py index 87a6d00b0..af27178e9 100644 --- a/discopop_library/discopop_optimizer/PETParser/PETParser.py +++ b/discopop_library/discopop_optimizer/PETParser/PETParser.py @@ -19,8 +19,8 @@ from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) -from discopop_explorer.classes.FunctionNode import FunctionNode -from discopop_explorer.classes.LoopNode import LoopNode +from discopop_explorer.classes.PEGraph.FunctionNode import FunctionNode +from discopop_explorer.classes.PEGraph.LoopNode import LoopNode from discopop_explorer.classes.PEGraph.CUNode import CUNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID diff --git a/discopop_library/discopop_optimizer/UpdateOptimization/RemoveLoopIndexUpdates.py b/discopop_library/discopop_optimizer/UpdateOptimization/RemoveLoopIndexUpdates.py index dd9ce4843..37b71f6f5 100644 --- a/discopop_library/discopop_optimizer/UpdateOptimization/RemoveLoopIndexUpdates.py +++ b/discopop_library/discopop_optimizer/UpdateOptimization/RemoveLoopIndexUpdates.py @@ -8,7 +8,7 @@ import logging from typing import List, Set, cast -from discopop_explorer.classes.LoopNode import LoopNode +from discopop_explorer.classes.PEGraph.LoopNode import LoopNode from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_library.discopop_optimizer.OptimizerArguments import OptimizerArguments from discopop_library.discopop_optimizer.Variables.Experiment import Experiment diff --git a/discopop_library/result_classes/MergedPattern.py b/discopop_library/result_classes/MergedPattern.py index 1bc0de6a2..1cf8ea491 100644 --- a/discopop_library/result_classes/MergedPattern.py +++ b/discopop_library/result_classes/MergedPattern.py @@ -8,7 +8,7 @@ from typing import List -from discopop_explorer.classes.Node import Node +from discopop_explorer.classes.PEGraph.Node import Node from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.result_classes.OptimizerOutputPattern import OptimizerOutputPattern diff --git a/discopop_library/result_classes/OptimizerOutputPattern.py b/discopop_library/result_classes/OptimizerOutputPattern.py index 2867028f8..c2fbf454d 100644 --- a/discopop_library/result_classes/OptimizerOutputPattern.py +++ b/discopop_library/result_classes/OptimizerOutputPattern.py @@ -9,7 +9,7 @@ import json from typing import Any, Dict, List -from discopop_explorer.classes.Node import Node +from discopop_explorer.classes.PEGraph.Node import Node from discopop_explorer.classes.patterns.PatternBase import PatternBase from discopop_library.PatternIdManagement.unique_pattern_id import get_unique_pattern_id From 129fbc67b2c8992a606e6bd2b47a5a2434016e25 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 31 Jul 2024 14:07:06 +0200 Subject: [PATCH 073/105] refactor: absolute imports --- discopop_explorer/__main__.py | 2 +- discopop_explorer/classes/PEGraph/PEGraphX.py | 5 +++- discopop_explorer/discopop_explorer.py | 4 ++-- discopop_explorer/json_serializer.py | 6 ++--- discopop_explorer/parallel_utils.py | 2 +- discopop_explorer/pattern_detection.py | 12 +++++----- .../pattern_detectors/device_updates.py | 4 ++-- .../pattern_detectors/do_all_detector.py | 18 +++++++-------- .../geometric_decomposition_detector.py | 8 +++---- .../pattern_detectors/pipeline_detector.py | 10 ++++---- .../pattern_detectors/reduction_detector.py | 16 ++++++------- .../simple_gpu_patterns/GPULoop.py | 12 +++++----- .../simple_gpu_patterns/GPURegions.py | 12 +++++----- discopop_explorer/plugins/pipeline.py | 6 ++--- .../DelaunayInterpolatedMicrobench.py | 4 ++-- .../ExtrapInterpolatedMicrobench.py | 9 ++++---- .../Microbench/MicrobenchParser.py | 2 +- .../Microbench/MixedMicrobench.py | 23 ++++++++----------- .../Microbench/PureDataMicrobench.py | 20 +++++++--------- .../discopop_optimizer/optimizer.py | 2 +- 20 files changed, 85 insertions(+), 92 deletions(-) diff --git a/discopop_explorer/__main__.py b/discopop_explorer/__main__.py index e88fe6297..dd523cbf4 100644 --- a/discopop_explorer/__main__.py +++ b/discopop_explorer/__main__.py @@ -11,7 +11,7 @@ from discopop_library.GlobalLogger.setup import setup_logger from discopop_library.PathManagement.PathManagement import get_path, get_path_or_none -from .discopop_explorer import ExplorerArguments, run +from discopop_explorer.discopop_explorer import ExplorerArguments, run def parse_args() -> ExplorerArguments: diff --git a/discopop_explorer/classes/PEGraph/PEGraphX.py b/discopop_explorer/classes/PEGraph/PEGraphX.py index 0f4af1a3d..0befe0a95 100644 --- a/discopop_explorer/classes/PEGraph/PEGraphX.py +++ b/discopop_explorer/classes/PEGraph/PEGraphX.py @@ -258,7 +258,10 @@ def calculateFunctionMetadata( print("Calculating local metadata results for functions...") import tqdm # type: ignore from multiprocessing import Pool - from ..parallel_utils import pet_function_metadata_initialize_worker, pet_function_metadata_parse_func + from discopop_explorer.parallel_utils import ( + pet_function_metadata_initialize_worker, + pet_function_metadata_parse_func, + ) param_list = func_nodes with Pool(initializer=pet_function_metadata_initialize_worker, initargs=(self,)) as pool: diff --git a/discopop_explorer/discopop_explorer.py b/discopop_explorer/discopop_explorer.py index 05ac53cc2..40bce76e9 100644 --- a/discopop_explorer/discopop_explorer.py +++ b/discopop_explorer/discopop_explorer.py @@ -30,9 +30,9 @@ ) from discopop_library.result_classes.DetectionResult import DetectionResult from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX -from .json_serializer import PatternBaseSerializer +from discopop_explorer.json_serializer import PatternBaseSerializer from discopop_explorer.utilities.PEGraphConstruction.parser import parse_inputs -from .pattern_detection import PatternDetectorX +from discopop_explorer.pattern_detection import PatternDetectorX from discopop_library.HostpotLoader.hostpot_loader import run as load_hotspots diff --git a/discopop_explorer/json_serializer.py b/discopop_explorer/json_serializer.py index d402f5234..0ae873057 100644 --- a/discopop_explorer/json_serializer.py +++ b/discopop_explorer/json_serializer.py @@ -15,9 +15,9 @@ from discopop_library.result_classes.DetectionResult import DetectionResult from discopop_library.result_classes.PatternStorage import PatternStorage from discopop_explorer.classes.PEGraph.Node import Node -from .pattern_detectors.pipeline_detector import PipelineStage -from .pattern_detectors.task_parallelism.classes import TPIType -from .classes.variable import Variable +from discopop_explorer.pattern_detectors.pipeline_detector import PipelineStage +from discopop_explorer.pattern_detectors.task_parallelism.classes import TPIType +from discopop_explorer.classes.variable import Variable def filter_members(d: Dict[Any, Any]) -> Dict[Any, Any]: diff --git a/discopop_explorer/parallel_utils.py b/discopop_explorer/parallel_utils.py index 9d4ea540f..a5085de01 100644 --- a/discopop_explorer/parallel_utils.py +++ b/discopop_explorer/parallel_utils.py @@ -9,7 +9,7 @@ from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.classes.PEGraph.FunctionNode import FunctionNode from discopop_explorer.classes.PEGraph.Node import Node -from .aliases.NodeID import NodeID +from discopop_explorer.aliases.NodeID import NodeID from typing import Any, List, Optional, Set, Tuple global_pet: Optional[PEGraphX] = None diff --git a/discopop_explorer/pattern_detection.py b/discopop_explorer/pattern_detection.py index 40fd7979d..d27080df8 100644 --- a/discopop_explorer/pattern_detection.py +++ b/discopop_explorer/pattern_detection.py @@ -23,12 +23,12 @@ from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.classes.PEGraph.DummyNode import DummyNode from discopop_explorer.classes.PEGraph.LoopNode import LoopNode -from .enums.EdgeType import EdgeType -from .pattern_detectors.do_all_detector import DoAllInfo, run_detection as detect_do_all -from .pattern_detectors.geometric_decomposition_detector import run_detection as detect_gd -from .pattern_detectors.pipeline_detector import run_detection as detect_pipeline -from .pattern_detectors.reduction_detector import ReductionInfo, run_detection as detect_reduction -from .pattern_detectors.simple_gpu_patterns.gpu_pattern_detector import run_detection as detect_gpu +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.pattern_detectors.do_all_detector import DoAllInfo, run_detection as detect_do_all +from discopop_explorer.pattern_detectors.geometric_decomposition_detector import run_detection as detect_gd +from discopop_explorer.pattern_detectors.pipeline_detector import run_detection as detect_pipeline +from discopop_explorer.pattern_detectors.reduction_detector import ReductionInfo, run_detection as detect_reduction +from discopop_explorer.pattern_detectors.simple_gpu_patterns.gpu_pattern_detector import run_detection as detect_gpu class PatternDetectorX(object): diff --git a/discopop_explorer/pattern_detectors/device_updates.py b/discopop_explorer/pattern_detectors/device_updates.py index ff0e020b9..79dad4290 100644 --- a/discopop_explorer/pattern_detectors/device_updates.py +++ b/discopop_explorer/pattern_detectors/device_updates.py @@ -12,8 +12,8 @@ PEGraphX, ) from discopop_explorer.classes.PEGraph.Node import Node -from ..aliases.MemoryRegion import MemoryRegion -from ..aliases.LineID import LineID +from discopop_explorer.aliases.MemoryRegion import MemoryRegion +from discopop_explorer.aliases.LineID import LineID class DeviceUpdateInfo(PatternInfo): diff --git a/discopop_explorer/pattern_detectors/do_all_detector.py b/discopop_explorer/pattern_detectors/do_all_detector.py index 6b40ecb21..13579d1f3 100644 --- a/discopop_explorer/pattern_detectors/do_all_detector.py +++ b/discopop_explorer/pattern_detectors/do_all_detector.py @@ -14,7 +14,7 @@ from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore from discopop_explorer.classes.patterns.PatternInfo import PatternInfo -from .reduction_detector import ReductionInfo +from discopop_explorer.pattern_detectors.reduction_detector import ReductionInfo from discopop_explorer.classes.PEGraph.PEGraphX import ( PEGraphX, ) @@ -22,14 +22,14 @@ from discopop_explorer.classes.PEGraph.CUNode import CUNode from discopop_explorer.classes.PEGraph.Node import Node from discopop_explorer.classes.PEGraph.Dependency import Dependency -from ..aliases.MemoryRegion import MemoryRegion -from ..aliases.LineID import LineID -from ..aliases.NodeID import NodeID -from ..enums.NodeType import NodeType -from ..enums.DepType import DepType -from ..enums.EdgeType import EdgeType -from ..utils import classify_loop_variables, filter_for_hotspots -from ..classes.variable import Variable +from discopop_explorer.aliases.MemoryRegion import MemoryRegion +from discopop_explorer.aliases.LineID import LineID +from discopop_explorer.aliases.NodeID import NodeID +from discopop_explorer.enums.NodeType import NodeType +from discopop_explorer.enums.DepType import DepType +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.utils import classify_loop_variables, filter_for_hotspots +from discopop_explorer.classes.variable import Variable class DoAllInfo(PatternInfo): diff --git a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py index a664e8d35..a38ba81a4 100644 --- a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py +++ b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py @@ -19,10 +19,10 @@ from discopop_explorer.classes.PEGraph.FunctionNode import FunctionNode from discopop_explorer.classes.PEGraph.LoopNode import LoopNode from discopop_explorer.classes.PEGraph.Node import Node -from ..aliases.NodeID import NodeID -from ..enums.EdgeType import EdgeType -from ..utils import classify_task_vars, filter_for_hotspots, get_child_loops -from ..classes.variable import Variable +from discopop_explorer.aliases.NodeID import NodeID +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.utils import classify_task_vars, filter_for_hotspots, get_child_loops +from discopop_explorer.classes.variable import Variable __loop_iterations: Dict[NodeID, int] = {} diff --git a/discopop_explorer/pattern_detectors/pipeline_detector.py b/discopop_explorer/pattern_detectors/pipeline_detector.py index 191438f4e..56c30fd7b 100644 --- a/discopop_explorer/pattern_detectors/pipeline_detector.py +++ b/discopop_explorer/pattern_detectors/pipeline_detector.py @@ -20,11 +20,11 @@ from discopop_explorer.classes.PEGraph.CUNode import CUNode from discopop_explorer.classes.PEGraph.Node import Node from discopop_explorer.classes.PEGraph.Dependency import Dependency -from ..aliases.LineID import LineID -from ..aliases.NodeID import NodeID -from ..enums.DepType import DepType -from ..enums.EdgeType import EdgeType -from ..utils import correlation_coefficient, classify_task_vars, filter_for_hotspots +from discopop_explorer.aliases.LineID import LineID +from discopop_explorer.aliases.NodeID import NodeID +from discopop_explorer.enums.DepType import DepType +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.utils import correlation_coefficient, classify_task_vars, filter_for_hotspots __pipeline_threshold = 0.9 diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index 5a27081c8..d216dca69 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -22,14 +22,14 @@ from discopop_explorer.classes.PEGraph.CUNode import CUNode from discopop_explorer.classes.PEGraph.Node import Node from discopop_explorer.classes.PEGraph.Dependency import Dependency -from ..aliases.MemoryRegion import MemoryRegion -from ..aliases.LineID import LineID -from ..aliases.NodeID import NodeID -from ..enums.NodeType import NodeType -from ..enums.DepType import DepType -from ..enums.EdgeType import EdgeType -from ..utils import filter_for_hotspots, is_reduction_var, classify_loop_variables -from ..classes.variable import Variable +from discopop_explorer.aliases.MemoryRegion import MemoryRegion +from discopop_explorer.aliases.LineID import LineID +from discopop_explorer.aliases.NodeID import NodeID +from discopop_explorer.enums.NodeType import NodeType +from discopop_explorer.enums.DepType import DepType +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.utils import filter_for_hotspots, is_reduction_var, classify_loop_variables +from discopop_explorer.classes.variable import Variable class ReductionInfo(PatternInfo): diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py index b7ac848ea..a916f20f6 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py @@ -16,15 +16,15 @@ from discopop_explorer.classes.PEGraph.LoopNode import LoopNode from discopop_explorer.classes.PEGraph.CUNode import CUNode from discopop_explorer.classes.PEGraph.Node import Node -from ...aliases.MemoryRegion import MemoryRegion -from ...aliases.LineID import LineID -from ...aliases.NodeID import NodeID -from ...enums.DepType import DepType +from discopop_explorer.aliases.MemoryRegion import MemoryRegion +from discopop_explorer.aliases.LineID import LineID +from discopop_explorer.aliases.NodeID import NodeID +from discopop_explorer.enums.DepType import DepType from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.utils import ( __get_dep_of_type as get_dep_of_type, ) -from ...utilities.PEGraphConstruction.ParserUtilities import parse_id +from discopop_explorer.utilities.PEGraphConstruction.ParserUtilities import parse_id from discopop_explorer.utils import ( is_scalar_val, is_loop_index2, @@ -43,7 +43,7 @@ from discopop_explorer.classes.variable import Variable from discopop_library.MemoryRegions.utils import get_sizes_of_memory_regions from discopop_library.result_classes.DetectionResult import DetectionResult -from .GPUMemory import getCalledFunctions, map_node +from discopop_explorer.pattern_detectors.simple_gpu_patterns.GPUMemory import getCalledFunctions, map_node """ def remove_duplicates(my_list: List) -> List: diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py index 6ebfb3d2c..4611029b8 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py @@ -16,13 +16,13 @@ from discopop_explorer.classes.PEGraph.LoopNode import LoopNode from discopop_explorer.classes.PEGraph.CUNode import CUNode from discopop_explorer.classes.PEGraph.Node import Node -from ...aliases.NodeID import NodeID -from ...enums.NodeType import NodeType -from ...enums.DepType import DepType -from ...enums.EdgeType import EdgeType +from discopop_explorer.aliases.NodeID import NodeID +from discopop_explorer.enums.NodeType import NodeType +from discopop_explorer.enums.DepType import DepType +from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.classes.variable import Variable -from .GPULoop import GPULoopPattern -from .GPUMemory import map_node +from discopop_explorer.pattern_detectors.simple_gpu_patterns.GPULoop import GPULoopPattern +from discopop_explorer.pattern_detectors.simple_gpu_patterns.GPUMemory import map_node from discopop_explorer.classes.patterns.PatternInfo import PatternInfo diff --git a/discopop_explorer/plugins/pipeline.py b/discopop_explorer/plugins/pipeline.py index 936676030..421fd2ffd 100644 --- a/discopop_explorer/plugins/pipeline.py +++ b/discopop_explorer/plugins/pipeline.py @@ -12,9 +12,9 @@ from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.classes.PEGraph.LoopNode import LoopNode from discopop_explorer.classes.PEGraph.Node import Node -from ..aliases.LineID import LineID -from ..enums.EdgeType import EdgeType -from ..utils import correlation_coefficient +from discopop_explorer.aliases.LineID import LineID +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.utils import correlation_coefficient total = 0 before: List[float] = [] diff --git a/discopop_library/discopop_optimizer/Microbench/DelaunayInterpolatedMicrobench.py b/discopop_library/discopop_optimizer/Microbench/DelaunayInterpolatedMicrobench.py index 676b3a2b9..8623abdd9 100644 --- a/discopop_library/discopop_optimizer/Microbench/DelaunayInterpolatedMicrobench.py +++ b/discopop_library/discopop_optimizer/Microbench/DelaunayInterpolatedMicrobench.py @@ -10,13 +10,13 @@ import numpy as np from scipy.interpolate import LinearNDInterpolator # type: ignore -from .Microbench import ( +from discopop_library.discopop_optimizer.Microbench.Microbench import ( Microbench, MicrobenchType, MicrobenchDimension, MicrobenchCoordinate, ) -from .PureDataMicrobench import PureDataMicrobench +from discopop_library.discopop_optimizer.Microbench.PureDataMicrobench import PureDataMicrobench # This class uses Delaunay Interpolation to create a microbench model from measurements. No extrapolation is possible diff --git a/discopop_library/discopop_optimizer/Microbench/ExtrapInterpolatedMicrobench.py b/discopop_library/discopop_optimizer/Microbench/ExtrapInterpolatedMicrobench.py index 59b65d248..00ee6e764 100644 --- a/discopop_library/discopop_optimizer/Microbench/ExtrapInterpolatedMicrobench.py +++ b/discopop_library/discopop_optimizer/Microbench/ExtrapInterpolatedMicrobench.py @@ -18,7 +18,7 @@ from extrap.modelers.multi_parameter.multi_parameter_modeler import MultiParameterModeler # type: ignore from sympy.parsing.sympy_parser import parse_expr # type: ignore -from .Microbench import ( +from discopop_library.discopop_optimizer.Microbench.Microbench import ( Microbench, MicrobenchType, MicrobenchDimension, @@ -75,10 +75,9 @@ def getFunctionSympy( expr = parse_expr(function_str, local_dict=function_mappings) return cast(sympy.Expr, expr) - def getMeasurements(self) -> Dict[ - MicrobenchType, - Dict[MicrobenchDimension, Dict[MicrobenchCoordinate, List[float]]], - ]: + def getMeasurements( + self, + ) -> Dict[MicrobenchType, Dict[MicrobenchDimension, Dict[MicrobenchCoordinate, List[float]]],]: raise NotImplementedError("TODO") # TODO def toJSON(self) -> str: diff --git a/discopop_library/discopop_optimizer/Microbench/MicrobenchParser.py b/discopop_library/discopop_optimizer/Microbench/MicrobenchParser.py index 3c11c7ccd..61191a180 100644 --- a/discopop_library/discopop_optimizer/Microbench/MicrobenchParser.py +++ b/discopop_library/discopop_optimizer/Microbench/MicrobenchParser.py @@ -9,7 +9,7 @@ from dataclasses import dataclass from typing import Dict, List, Tuple -from .Microbench import ( +from discopop_library.discopop_optimizer.Microbench.Microbench import ( MicrobenchType, MicrobenchCoordinate, MicrobenchDimension, diff --git a/discopop_library/discopop_optimizer/Microbench/MixedMicrobench.py b/discopop_library/discopop_optimizer/Microbench/MixedMicrobench.py index 960a4648e..fc833807b 100644 --- a/discopop_library/discopop_optimizer/Microbench/MixedMicrobench.py +++ b/discopop_library/discopop_optimizer/Microbench/MixedMicrobench.py @@ -7,8 +7,12 @@ # directory for details. from typing import Dict, List, Tuple, Union -from .Microbench import Microbench -from .Microbench import MicrobenchCoordinate, MicrobenchDimension, MicrobenchType +from discopop_library.discopop_optimizer.Microbench.Microbench import ( + Microbench, + MicrobenchCoordinate, + MicrobenchDimension, + MicrobenchType, +) # This class can be used to mix two microbench models. @@ -26,28 +30,19 @@ def __init__(self, inner: Microbench, outer: Microbench, threshold: MicrobenchCo def getMeasurements( self, - ) -> Dict[ - MicrobenchType, - Dict[MicrobenchDimension, Dict[MicrobenchCoordinate, List[float]]], - ]: + ) -> Dict[MicrobenchType, Dict[MicrobenchDimension, Dict[MicrobenchCoordinate, List[float]]],]: raise TypeError( "This MixedMicrobench might be based on two different sets of measurements. Use getInnerMeasurements() or getOuterMeasurements() instead." ) def getInnerMeasurements( self, - ) -> Dict[ - MicrobenchType, - Dict[MicrobenchDimension, Dict[MicrobenchCoordinate, List[float]]], - ]: + ) -> Dict[MicrobenchType, Dict[MicrobenchDimension, Dict[MicrobenchCoordinate, List[float]]],]: return self.inner.getMeasurements() def getOuterMeasurements( self, - ) -> Dict[ - MicrobenchType, - Dict[MicrobenchDimension, Dict[MicrobenchCoordinate, List[float]]], - ]: + ) -> Dict[MicrobenchType, Dict[MicrobenchDimension, Dict[MicrobenchCoordinate, List[float]]],]: return self.outer.getMeasurements() def toJSON(self) -> str: diff --git a/discopop_library/discopop_optimizer/Microbench/PureDataMicrobench.py b/discopop_library/discopop_optimizer/Microbench/PureDataMicrobench.py index 5f2b310ed..8d79d9a73 100644 --- a/discopop_library/discopop_optimizer/Microbench/PureDataMicrobench.py +++ b/discopop_library/discopop_optimizer/Microbench/PureDataMicrobench.py @@ -13,7 +13,7 @@ import numpy as np -from .Microbench import ( +from discopop_library.discopop_optimizer.Microbench.Microbench import ( Microbench, MicrobenchType, MicrobenchDimension, @@ -52,17 +52,16 @@ class PureDataMicrobench(Microbench): ] @overload - def __getitem__( - self, key: MicrobenchType - ) -> Dict[MicrobenchDimension, Dict[MicrobenchCoordinate, List[float]]]: ... + def __getitem__(self, key: MicrobenchType) -> Dict[MicrobenchDimension, Dict[MicrobenchCoordinate, List[float]]]: + ... @overload - def __getitem__( - self, key: Tuple[MicrobenchType, MicrobenchDimension] - ) -> Dict[MicrobenchCoordinate, List[float]]: ... + def __getitem__(self, key: Tuple[MicrobenchType, MicrobenchDimension]) -> Dict[MicrobenchCoordinate, List[float]]: + ... @overload - def __getitem__(self, key: Tuple[MicrobenchType, MicrobenchDimension, MicrobenchCoordinate]) -> List[float]: ... + def __getitem__(self, key: Tuple[MicrobenchType, MicrobenchDimension, MicrobenchCoordinate]) -> List[float]: + ... # allow to use this class like a dictionary def __getitem__(self, key: Any) -> Any: @@ -182,10 +181,7 @@ def mergeAll(self, others: List[PureDataMicrobench]) -> None: # inherited from Microbench def getMeasurements( self, - ) -> Dict[ - MicrobenchType, - Dict[MicrobenchDimension, Dict[MicrobenchCoordinate, List[float]]], - ]: + ) -> Dict[MicrobenchType, Dict[MicrobenchDimension, Dict[MicrobenchCoordinate, List[float]]],]: return self.measurements # inherited from Microbench diff --git a/discopop_library/discopop_optimizer/optimizer.py b/discopop_library/discopop_optimizer/optimizer.py index 4ad84bee7..c9bc1a0b9 100644 --- a/discopop_library/discopop_optimizer/optimizer.py +++ b/discopop_library/discopop_optimizer/optimizer.py @@ -73,7 +73,7 @@ ) from discopop_library.discopop_optimizer.suggestions.importers.main import import_suggestions -from ..HostpotLoader.hostpot_loader import run as load_hotspots +from discopop_library.HostpotLoader.hostpot_loader import run as load_hotspots def run(arguments: OptimizerArguments) -> None: From 29242fdc486abdb288b5f8ff620d671dd4f67856 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Thu, 1 Aug 2024 15:03:27 +0200 Subject: [PATCH 074/105] refactor: separate functions from PEGraphX --- .../classes/PEGraph/FunctionNode.py | 9 +- discopop_explorer/classes/PEGraph/LoopNode.py | 10 +- discopop_explorer/classes/PEGraph/NodeT.py | 15 + discopop_explorer/classes/PEGraph/PEGraphX.py | 742 +----------------- discopop_explorer/discopop_explorer.py | 3 +- .../functions/PEGraph/__init__.py | 0 .../functions/PEGraph/output/gephi.py | 32 + .../functions/PEGraph/output/json.py | 23 + .../PEGraph/properties/check_reachability.py | 37 + .../properties/depends_ignore_readonly.py | 75 ++ .../PEGraph/properties/is_loop_index.py | 44 ++ .../properties/is_passed_by_reference.py | 20 + .../PEGraph/properties/is_predecessor.py | 52 ++ .../is_readonly_inside_loop_body.py | 53 ++ .../properties/is_reduction_var_by_name.py | 23 + .../PEGraph/properties/is_scalar_val.py | 25 + .../functions/PEGraph/queries/edges.py | 49 ++ .../PEGraph/queries/memory_regions.py | 26 + .../functions/PEGraph/queries/nodes.py | 34 + .../functions/PEGraph/queries/paths.py | 80 ++ .../functions/PEGraph/queries/reductions.py | 22 + .../functions/PEGraph/queries/subtree.py | 111 +++ .../functions/PEGraph/queries/variables.py | 116 +++ .../functions/PEGraph/traversal/__init__.py | 0 .../functions/PEGraph/traversal/children.py | 48 ++ .../functions/PEGraph/traversal/parent.py | 43 + .../functions/PEGraph/traversal/successors.py | 27 + .../functions/PEGraph/unused/__init__.py | 0 .../PEGraph/unused/unused_functions.py | 114 +++ discopop_explorer/functions/__init__.py | 0 discopop_explorer/parallel_utils.py | 6 +- discopop_explorer/pattern_detection.py | 6 +- .../CombinedGPURegions.py | 17 +- .../classes/EntryPoint.py | 5 +- .../classes/ExitPoint.py | 5 +- .../combined_gpu_patterns/classes/Update.py | 12 +- .../combined_gpu_patterns/step_1.py | 17 +- .../combined_gpu_patterns/step_2.py | 28 +- .../combined_gpu_patterns/step_3.py | 16 +- .../combined_gpu_patterns/step_4.py | 45 +- .../combined_gpu_patterns/step_5.py | 3 +- .../combined_gpu_patterns/step_6.py | 31 +- .../combined_gpu_patterns/utilities.py | 7 +- .../pattern_detectors/do_all_detector.py | 57 +- .../geometric_decomposition_detector.py | 22 +- .../pattern_detectors/pipeline_detector.py | 30 +- .../pattern_detectors/reduction_detector.py | 38 +- .../simple_gpu_patterns/GPULoop.py | 56 +- .../simple_gpu_patterns/GPUMemory.py | 5 +- .../simple_gpu_patterns/GPURegions.py | 27 +- .../gpu_pattern_detector.py | 5 +- .../task_parallelism/filter.py | 14 +- .../task_parallelism/postprocessor.py | 7 +- .../task_parallelism/preprocessor.py | 6 +- .../task_parallelism/suggesters/auxiliary.py | 3 +- .../task_parallelism/suggesters/barriers.py | 23 +- .../suggesters/data_sharing_clauses.py | 3 +- .../suggesters/dependency_clauses.py | 38 +- .../task_parallelism/suggesters/tasks.py | 22 +- .../task_parallelism_detector.py | 6 +- .../task_parallelism/tp_utils.py | 31 +- discopop_explorer/plugins/pipeline.py | 12 +- .../utilities/general/generate_Data_CUInst.py | 17 +- discopop_explorer/utils.py | 79 +- 64 files changed, 1518 insertions(+), 1014 deletions(-) create mode 100644 discopop_explorer/classes/PEGraph/NodeT.py create mode 100644 discopop_explorer/functions/PEGraph/__init__.py create mode 100644 discopop_explorer/functions/PEGraph/output/gephi.py create mode 100644 discopop_explorer/functions/PEGraph/output/json.py create mode 100644 discopop_explorer/functions/PEGraph/properties/check_reachability.py create mode 100644 discopop_explorer/functions/PEGraph/properties/depends_ignore_readonly.py create mode 100644 discopop_explorer/functions/PEGraph/properties/is_loop_index.py create mode 100644 discopop_explorer/functions/PEGraph/properties/is_passed_by_reference.py create mode 100644 discopop_explorer/functions/PEGraph/properties/is_predecessor.py create mode 100644 discopop_explorer/functions/PEGraph/properties/is_readonly_inside_loop_body.py create mode 100644 discopop_explorer/functions/PEGraph/properties/is_reduction_var_by_name.py create mode 100644 discopop_explorer/functions/PEGraph/properties/is_scalar_val.py create mode 100644 discopop_explorer/functions/PEGraph/queries/edges.py create mode 100644 discopop_explorer/functions/PEGraph/queries/memory_regions.py create mode 100644 discopop_explorer/functions/PEGraph/queries/nodes.py create mode 100644 discopop_explorer/functions/PEGraph/queries/paths.py create mode 100644 discopop_explorer/functions/PEGraph/queries/reductions.py create mode 100644 discopop_explorer/functions/PEGraph/queries/subtree.py create mode 100644 discopop_explorer/functions/PEGraph/queries/variables.py create mode 100644 discopop_explorer/functions/PEGraph/traversal/__init__.py create mode 100644 discopop_explorer/functions/PEGraph/traversal/children.py create mode 100644 discopop_explorer/functions/PEGraph/traversal/parent.py create mode 100644 discopop_explorer/functions/PEGraph/traversal/successors.py create mode 100644 discopop_explorer/functions/PEGraph/unused/__init__.py create mode 100644 discopop_explorer/functions/PEGraph/unused/unused_functions.py create mode 100644 discopop_explorer/functions/__init__.py diff --git a/discopop_explorer/classes/PEGraph/FunctionNode.py b/discopop_explorer/classes/PEGraph/FunctionNode.py index d95d07ef7..2a97ae23e 100644 --- a/discopop_explorer/classes/PEGraph/FunctionNode.py +++ b/discopop_explorer/classes/PEGraph/FunctionNode.py @@ -19,6 +19,7 @@ from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.classes.variable import Variable +from discopop_explorer.functions.PEGraph.queries.edges import in_edges, out_edges if TYPE_CHECKING: from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX @@ -42,8 +43,8 @@ def __init__(self, node_id: NodeID): self.memory_accesses_present = False def get_entry_cu_id(self, pet: PEGraphX) -> NodeID: - for child_cu_id in [t for s, t, d in pet.out_edges(self.id, EdgeType.CHILD)]: - if len(pet.in_edges(child_cu_id, EdgeType.SUCCESSOR)) == 0: + for child_cu_id in [t for s, t, d in out_edges(pet, self.id, EdgeType.CHILD)]: + if len(in_edges(pet, child_cu_id, EdgeType.SUCCESSOR)) == 0: return child_cu_id raise ValueError("Mal-formatted function: ", self.id, " - No entry CU found!") @@ -52,8 +53,8 @@ def get_exit_cu_ids(self, pet: PEGraphX) -> Set[NodeID]: if self.children_cu_ids is not None: for child_cu_id in self.children_cu_ids: if ( - len(pet.out_edges(child_cu_id, EdgeType.SUCCESSOR)) == 0 - and len(pet.in_edges(child_cu_id, EdgeType.SUCCESSOR)) != 0 + len(out_edges(pet, child_cu_id, EdgeType.SUCCESSOR)) == 0 + and len(in_edges(pet, child_cu_id, EdgeType.SUCCESSOR)) != 0 ): exit_cu_ids.add(child_cu_id) return exit_cu_ids diff --git a/discopop_explorer/classes/PEGraph/LoopNode.py b/discopop_explorer/classes/PEGraph/LoopNode.py index c547a3709..0e2d4ca32 100644 --- a/discopop_explorer/classes/PEGraph/LoopNode.py +++ b/discopop_explorer/classes/PEGraph/LoopNode.py @@ -14,6 +14,8 @@ from discopop_explorer.classes.PEGraph.Node import Node from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.enums.NodeType import NodeType +from discopop_explorer.functions.PEGraph.queries.edges import in_edges +from discopop_explorer.functions.PEGraph.traversal.children import direct_children from discopop_explorer.utilities.PEGraphConstruction.classes.LoopData import LoopData if TYPE_CHECKING: @@ -46,7 +48,7 @@ def get_nesting_level(self, pet: PEGraphX, return_invert_result: bool = True) -> } } """ - parents = [s for s, t, d in pet.in_edges(self.id, EdgeType.CHILD)] + parents = [s for s, t, d in in_edges(pet, self.id, EdgeType.CHILD)] # count levels upwards parent_nesting_levels: List[int] = [] @@ -73,11 +75,11 @@ def get_nesting_level(self, pet: PEGraphX, return_invert_result: bool = True) -> def get_entry_node(self, pet: PEGraphX) -> Optional[Node]: """returns the first CU Node contained in the loop (i.e. one without predecessor inside the loop)""" - for node in pet.direct_children(self): + for node in direct_children(pet, self): predecessors_outside_loop_body = [ s - for s, t, d in pet.in_edges(node.id, EdgeType.SUCCESSOR) - if pet.node_at(s) not in pet.direct_children(self) + for s, t, d in in_edges(pet, node.id, EdgeType.SUCCESSOR) + if pet.node_at(s) not in direct_children(pet, self) ] if len(predecessors_outside_loop_body) > 0: return node diff --git a/discopop_explorer/classes/PEGraph/NodeT.py b/discopop_explorer/classes/PEGraph/NodeT.py new file mode 100644 index 000000000..4f1463e5c --- /dev/null +++ b/discopop_explorer/classes/PEGraph/NodeT.py @@ -0,0 +1,15 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +# generic type for subclasses of Node +from typing import TypeVar + +from discopop_explorer.classes.PEGraph.Node import Node + + +NodeT = TypeVar("NodeT", bound=Node) diff --git a/discopop_explorer/classes/PEGraph/PEGraphX.py b/discopop_explorer/classes/PEGraph/PEGraphX.py index 0befe0a95..d3f606137 100644 --- a/discopop_explorer/classes/PEGraph/PEGraphX.py +++ b/discopop_explorer/classes/PEGraph/PEGraphX.py @@ -18,6 +18,16 @@ from alive_progress import alive_bar # type: ignore from lxml.objectify import ObjectifiedElement # type: ignore +from discopop_explorer.classes.PEGraph.NodeT import NodeT +from discopop_explorer.functions.PEGraph.properties.is_loop_index import is_loop_index +from discopop_explorer.functions.PEGraph.properties.is_readonly_inside_loop_body import is_readonly_inside_loop_body +from discopop_explorer.functions.PEGraph.queries.edges import in_edges, out_edges +from discopop_explorer.functions.PEGraph.queries.nodes import all_nodes +from discopop_explorer.functions.PEGraph.queries.subtree import subtree_of_type +from discopop_explorer.functions.PEGraph.queries.variables import get_variables +from discopop_explorer.functions.PEGraph.traversal.children import direct_children, direct_children_or_called_nodes +from discopop_explorer.functions.PEGraph.traversal.parent import get_parent_function +from discopop_explorer.functions.PEGraph.traversal.successors import direct_successors from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType from discopop_library.HostpotLoader.HotspotType import HotspotType # type:ignore from discopop_explorer.aliases.LineID import LineID @@ -189,8 +199,8 @@ def map_static_and_dynamic_dependencies(self) -> None: print("\t\tIdentifying mappings between static and dynamic memory regions...", end=" ") mem_reg_mappings: Dict[MemoryRegion, Set[MemoryRegion]] = dict() # initialize mappings - for node_id in [n.id for n in self.all_nodes(CUNode)]: - out_deps = [(s, t, d) for s, t, d in self.out_edges(node_id) if d.etype == EdgeType.DATA] + for node_id in [n.id for n in all_nodes(self, CUNode)]: + out_deps = [(s, t, d) for s, t, d in out_edges(self, node_id) if d.etype == EdgeType.DATA] # for outgoing dependencies, the scope must be equal # as a result, comparing variable names to match memory regions is valid @@ -212,8 +222,8 @@ def map_static_and_dynamic_dependencies(self) -> None: print("\t\tInstantiating static dependencies...", end=" ") # create copies of static dependency edges for all dynamic mappings - for node_id in [n.id for n in self.all_nodes(CUNode)]: - out_deps = [(s, t, d) for s, t, d in self.out_edges(node_id) if d.etype == EdgeType.DATA] + for node_id in [n.id for n in all_nodes(self, CUNode)]: + out_deps = [(s, t, d) for s, t, d in out_edges(self, node_id) if d.etype == EdgeType.DATA] for s, t, d in out_deps: if d.memory_region is None: continue @@ -239,7 +249,7 @@ def calculateFunctionMetadata( # store id of parent function in each node # and store in each function node a list of all children ids if func_nodes is None: - func_nodes = self.all_nodes(FunctionNode) + func_nodes = all_nodes(self, FunctionNode) if hotspot_information is not None: all_hotspot_functions: Set[Tuple[int, str]] = set() @@ -286,8 +296,8 @@ def calculateFunctionMetadata( if False: print("Cleaning duplicated dependencies...") to_be_removed = [] - for cu_node in self.all_nodes(CUNode): - out_deps = self.out_edges(cu_node.id, EdgeType.DATA) + for cu_node in all_nodes(self, CUNode): + out_deps = out_edges(self, cu_node.id, EdgeType.DATA) for dep_1 in out_deps: for dep_2 in out_deps: if dep_1 == dep_2: @@ -319,8 +329,8 @@ def calculateFunctionMetadata( # cleanup dependencies II : only consider the Intra-iteration dependencies with the highest level print("Cleaning duplicated dependencies II...") to_be_removed = [] - for cu_node in self.all_nodes(CUNode): - out_deps = self.out_edges(cu_node.id, EdgeType.DATA) + for cu_node in all_nodes(self, CUNode): + out_deps = out_edges(self, cu_node.id, EdgeType.DATA) for dep_1 in out_deps: for dep_2 in out_deps: if dep_1 == dep_2: @@ -355,9 +365,9 @@ def calculateLoopMetadata(self) -> None: # calculate loop indices print("Calculating loop indices") - loop_nodes = self.all_nodes(LoopNode) + loop_nodes = all_nodes(self, LoopNode) for loop in loop_nodes: - subtree = self.subtree_of_type(loop, CUNode) + subtree = subtree_of_type(self, loop, CUNode) # get variables used in loop candidates: Set[Variable] = set() for node in subtree: @@ -365,7 +375,7 @@ def calculateLoopMetadata(self) -> None: # identify loop indices loop_indices: Set[Variable] = set() for v in candidates: - if self.is_loop_index(v.name, [loop.start_position()], subtree): + if is_loop_index(self, v.name, [loop.start_position()], subtree): loop_indices.add(v) loop.loop_indices = [v.name for v in loop_indices] print("\tDone.") @@ -469,103 +479,6 @@ def node_at(self, node_id: NodeID) -> Node: """ return cast(Node, self.g.nodes[node_id]["data"]) - # generic type for subclasses of Node - NodeT = TypeVar("NodeT", bound=Node) - - @overload - def all_nodes(self) -> List[Node]: - ... - - @overload - def all_nodes(self, type: Union[Type[NodeT], Tuple[Type[NodeT], ...]]) -> List[NodeT]: - ... - - def all_nodes(self, type: Any = Node) -> List[NodeT]: - """List of all nodes of specified type - - :param type: type(s) of nodes - :return: List of all nodes - """ - return [n[1] for n in self.g.nodes(data="data") if isinstance(n[1], type)] - - def out_edges( - self, node_id: NodeID, etype: Optional[Union[EdgeType, List[EdgeType]]] = None - ) -> List[Tuple[NodeID, NodeID, Dependency]]: - """Get outgoing edges of node of specified type - - :param node_id: id of the source node - :param etype: type of edges - :return: list of outgoing edges - """ - if etype is None: - return [t for t in self.g.out_edges(node_id, data="data")] - elif type(etype) == list: - return [t for t in self.g.out_edges(node_id, data="data") if t[2].etype in etype] - else: - return [t for t in self.g.out_edges(node_id, data="data") if t[2].etype == etype] - - def in_edges( - self, node_id: NodeID, etype: Optional[Union[EdgeType, List[EdgeType]]] = None - ) -> List[Tuple[NodeID, NodeID, Dependency]]: - """Get incoming edges of node of specified type - - :param node_id: id of the target node - :param etype: type of edges - :return: list of incoming edges - """ - if etype is None: - return [t for t in self.g.in_edges(node_id, data="data")] - elif type(etype) == list: - return [t for t in self.g.in_edges(node_id, data="data") if t[2].etype in etype] - else: - return [t for t in self.g.in_edges(node_id, data="data") if t[2].etype == etype] - - @overload - def subtree_of_type(self, root: Node) -> List[Node]: - ... - - @overload - def subtree_of_type(self, root: Node, type: Union[Type[NodeT], Tuple[Type[NodeT], ...]]) -> List[NodeT]: - ... - - def subtree_of_type(self, root: Node, type: Any = Node) -> List[NodeT]: - """Gets all nodes in subtree of specified type including root - - :param root: root node - :param type: type of children, None is equal to a wildcard - :return: list of nodes in subtree - """ - return self.subtree_of_type_rec(root, set(), type) - - @overload - def subtree_of_type_rec(self, root: Node, visited: Set[Node]) -> List[Node]: - ... - - @overload - def subtree_of_type_rec( - self, root: Node, visited: Set[Node], type: Union[Type[NodeT], Tuple[Type[NodeT], ...]] - ) -> List[NodeT]: - ... - - def subtree_of_type_rec(self, root: Node, visited: Set[Node], type: Any = Node) -> List[NodeT]: - """recursive helper function for subtree_of_type""" - # check if root is of type target - res = [] - if isinstance(root, type): - res.append(root) - - # append root to visited - visited.add(root) - - # enter recursion - for _, target, _ in self.out_edges(root.id, [EdgeType.CHILD, EdgeType.CALLSNODE]): - # prevent cycles - if self.node_at(target) in visited: - continue - res += self.subtree_of_type_rec(self.node_at(target), visited, type) - - return res - def __cu_equal__(self, cu_1: Node, cu_2: Node) -> bool: """Alternative to CUNode.__eq__, bypasses the isinstance-check and relies on MyPy for type safety. :param cu_1: CUNode 1 @@ -577,7 +490,7 @@ def __cu_equal__(self, cu_1: Node, cu_2: Node) -> bool: def get_node_parent_id(self, node: Node) -> Optional[NodeID]: """Returns the id of the FunctionNode which is the parent of the given node""" - parents = [s for s, t, d in self.in_edges(node.id, EdgeType.CHILD)] + parents = [s for s, t, d in in_edges(self, node.id, EdgeType.CHILD)] if len(parents) == 0: return None elif len(parents) == 1: @@ -593,168 +506,6 @@ def get_node_parent_id(self, node: Node) -> Optional[NodeID]: return parent return None - def direct_successors(self, root: Node) -> List[Node]: - """Gets only direct successors of any type - - :param root: root node - :return: list of direct successors - """ - return [self.node_at(t) for s, t, d in self.out_edges(root.id, EdgeType.SUCCESSOR)] - - def direct_children_or_called_nodes(self, root: Node) -> List[Node]: - """Gets direct children of any type. Also includes nodes of called functions - - :param root: root node - :return: list of direct children - """ - return [self.node_at(t) for s, t, d in self.out_edges(root.id, [EdgeType.CHILD, EdgeType.CALLSNODE])] - - def direct_children(self, root: Node) -> List[Node]: - """Gets direct children of any type. This includes called nodes! - - :param root: root node - :return: list of direct children - """ - return [self.node_at(t) for s, t, d in self.out_edges(root.id, EdgeType.CHILD)] - - def direct_children_or_called_nodes_of_type(self, root: Node, type: Type[NodeT]) -> List[NodeT]: - """Gets only direct children of specified type. This includes called nodes! - - :param root: root node - :param type: type of children - :return: list of direct children - """ - nodes = [self.node_at(t) for s, t, d in self.out_edges(root.id, [EdgeType.CHILD, EdgeType.CALLSNODE])] - - return [t for t in nodes if isinstance(t, type)] - - def is_reduction_var(self, line: LineID, name: str) -> bool: - """Determines, whether or not the given variable is reduction variable - - :param line: loop line number - :param name: variable name - :return: true if is reduction variable - """ - return any(rv for rv in self.reduction_vars if rv["loop_line"] == line and rv["name"] == name) - - def depends_ignore_readonly(self, source: Node, target: Node, root_loop: Node) -> bool: - """Detects if source node or one of it's children has a RAW dependency to target node or one of it's children - The loop index and readonly variables are ignored. - - :param source: source node for dependency detection (later occurrence in the source code) - :param target: target of dependency (prior occurrence in the source code) - :param root_loop: root loop - :return: true, if there is RAW dependency""" - if source == target: - return False - - # get recursive children of source and target - source_children_ids = [node.id for node in self.subtree_of_type(source, CUNode)] - target_children_ids = [node.id for node in self.subtree_of_type(target, CUNode)] - - # get required metadata - loop_start_lines: List[LineID] = [] - root_children = self.subtree_of_type(root_loop, (CUNode, LoopNode)) - root_children_cus = [cu for cu in root_children if isinstance(cu, CUNode)] - root_children_loops = [cu for cu in root_children if isinstance(cu, LoopNode)] - for v in root_children_loops: - loop_start_lines.append(v.start_position()) - - # check for RAW dependencies between any of source_children and any of target_children - for source_child_id in source_children_ids: - # get a list of filtered dependencies, outgoing from source_child - out_deps = self.out_edges(source_child_id, EdgeType.DATA) - out_raw_deps = [dep for dep in out_deps if dep[2].dtype == DepType.RAW] - filtered_deps = [ - elem - for elem in out_raw_deps - if not self.is_readonly_inside_loop_body( - elem[2], - root_loop, - root_children_cus, - root_children_loops, - loops_start_lines=loop_start_lines, - ) - ] - filtered_deps = [ - elem - for elem in filtered_deps - if not self.is_loop_index(elem[2].var_name, loop_start_lines, root_children_cus) - ] - # get a list of dependency targets - dep_targets = [t for _, t, _ in filtered_deps] - # check if overlap between dependency targets and target_children exists. - overlap = [node_id for node_id in dep_targets if node_id in target_children_ids] - if len(overlap) > 0: - # if so, a RAW dependency exists - return True - return False - - def unused_check_alias(self, s: NodeID, t: NodeID, d: Dependency, root_loop: Node) -> bool: - sub = self.subtree_of_type(root_loop, CUNode) - parent_func_sink = self.get_parent_function(self.node_at(s)) - parent_func_source = self.get_parent_function(self.node_at(t)) - - res = False - d_var_name_str = cast(str, d.var_name) - - if self.unused_is_global(d_var_name_str, sub) and not ( - self.is_passed_by_reference(d, parent_func_sink) and self.is_passed_by_reference(d, parent_func_source) - ): - return res - return not res - - def unused_is_global(self, var: str, tree: Sequence[Node]) -> bool: - """Checks if variable is global - - :param var: variable name - :param tree: nodes to search - :return: true if global - """ - - for node in tree: - if isinstance(node, CUNode): - for gv in node.global_vars: - if gv.name == var: - # TODO from tmp global vars - return False - return False - - def is_passed_by_reference(self, dep: Dependency, func: FunctionNode) -> bool: - res = False - - for i in func.args: - if i.name == dep.var_name: - return True - return False - - def unused_get_first_written_vars_in_loop( - self, undefinedVarsInLoop: List[Variable], node: Node, root_loop: Node - ) -> Set[Variable]: - root_children = self.subtree_of_type(root_loop, CUNode) - loop_node_ids = [n.id for n in root_children] - fwVars = set() - - raw = set() - war = set() - waw = set() - sub = root_children - for sub_node in sub: - raw.update(self.get_dep(sub_node, DepType.RAW, False)) - war.update(self.get_dep(sub_node, DepType.WAR, False)) - waw.update(self.get_dep(sub_node, DepType.WAW, False)) - - for var in undefinedVarsInLoop: - if var not in fwVars: - for i in raw: - if i[2].var_name == var and i[0] in loop_node_ids and i[1] in loop_node_ids: - for e in itertools.chain(war, waw): - if e[2].var_name == var and e[0] in loop_node_ids and e[1] in loop_node_ids: - if e[2].sink_line == i[2].source_line: - fwVars.add(var) - - return fwVars - def get_dep(self, node: Node, dep_type: DepType, reversed: bool) -> List[Tuple[NodeID, NodeID, Dependency]]: """Searches all dependencies of specified type @@ -765,250 +516,10 @@ def get_dep(self, node: Node, dep_type: DepType, reversed: bool) -> List[Tuple[N """ return [ e - for e in (self.in_edges(node.id, EdgeType.DATA) if reversed else self.out_edges(node.id, EdgeType.DATA)) + for e in (in_edges(self, node.id, EdgeType.DATA) if reversed else out_edges(self, node.id, EdgeType.DATA)) if e[2].dtype == dep_type ] - def is_scalar_val(self, allVars: List[Variable], var: str) -> bool: - """Checks if variable is a scalar value - - :param var: variable - :return: true if scalar - """ - for x in allVars: - if x.name == var: - return not (x.type.endswith("**") or x.type.startswith("ARRAY") or x.type.startswith("[")) - else: - return False - raise ValueError("allVars must not be empty.") - - def get_variables(self, nodes: Sequence[Node]) -> Dict[Variable, Set[MemoryRegion]]: - """Gets all variables and corresponding memory regions in nodes - - :param nodes: nodes - :return: Set of variables - """ - res: Dict[Variable, Set[MemoryRegion]] = dict() - for node in nodes: - if isinstance(node, CUNode): - for v in node.local_vars: - if v not in res: - res[v] = set() - for v in node.global_vars: - if v not in res: - res[v] = set() - # try to identify memory regions - for var_name in res: - # since the variable name is checked for equality afterwards, - # it is safe to consider incoming dependencies at this point as well. - # Note that INIT type edges are considered as well! - for _, _, dep in self.out_edges(node.id, EdgeType.DATA) + self.in_edges(node.id, EdgeType.DATA): - if dep.var_name == var_name.name: - if dep.memory_region is not None: - res[var_name].add(dep.memory_region) - return res - - def get_undefined_variables_inside_loop( - self, root_loop: Node, include_global_vars: bool = False - ) -> Dict[Variable, Set[MemoryRegion]]: - sub = self.subtree_of_type(root_loop, CUNode) - vars = self.get_variables(sub) - dummyVariables = [] - definedVarsInLoop = [] - definedVarsInCalledFunctions = [] - - # Remove llvm temporary variables - for var in vars: - if var.defLine == "LineNotFound" or "0:" in var.defLine: - dummyVariables.append(var) - elif not include_global_vars: - if var.defLine == "GlobalVar" and not self.is_reduction_var(root_loop.start_position(), var.name): - dummyVariables.append(var) - - # vars = list(set(vars) ^ set(dummyVariables)) - for key in set(dummyVariables): - if key in vars: - del vars[key] - - # Exclude variables which are defined inside the loop - for var in vars: - if var.defLine >= root_loop.start_position() and var.defLine <= root_loop.end_position(): - definedVarsInLoop.append(var) - - # vars = list(set(vars) ^ set(definedVarsInLoop)) - for key in set(definedVarsInLoop): - if key in vars: - del vars[key] - - # Also, exclude variables which are defined inside - # functions that are called within the loop - for var in vars: - for s in sub: - if var.defLine >= s.start_position() and var.defLine <= s.end_position(): - definedVarsInCalledFunctions.append(var) - - # vars = list(set(vars) ^ set(definedVarsInCalledFunctions)) - for key in set(definedVarsInCalledFunctions): - if key in vars: - del vars[key] - - return vars - - def unused_is_first_written_in_loop(self, dep: Dependency, root_loop: Node) -> bool: - """Checks whether a variable is first written inside the current node - - :param var: - :param raw_deps: raw dependencies of the loop - :param war_deps: war dependencies of the loop - :param reverse_raw_deps: - :param reverse_war_deps: - :param tree: subtree of the loop - :return: true if first written - """ - - result = False - children = self.subtree_of_type(root_loop, CUNode) - - for v in children: - for t, d in [ - (t, d) - for s, t, d in self.out_edges(v.id, EdgeType.DATA) - if d.dtype == DepType.WAR or d.dtype == DepType.WAW - ]: - if d.var_name is None: - return False - assert d.var_name is not None - if dep.var_name == d.var_name: - if dep.source_line == d.sink_line: - result = True - break - # None may occur because __get_variables doesn't check for actual elements - return result - - def is_loop_index(self, var_name: Optional[str], loops_start_lines: List[LineID], children: Sequence[Node]) -> bool: - """Checks, whether the variable is a loop index. - - :param var_name: name of the variable - :param loops_start_lines: start lines of the loops - :param children: children nodes of the loops - :return: true if edge represents loop index - """ - - # If there is a raw dependency for var, the source cu is part of the loop - # and the dependency occurs in loop header, then var is loop index+ - - for c in children: - for t, d in [ - (t, d) - for s, t, d in self.out_edges(c.id, EdgeType.DATA) - if d.dtype == DepType.RAW and d.var_name == var_name - ]: - if d.sink_line == d.source_line and d.source_line in loops_start_lines and self.node_at(t) in children: - return True - - return False - - def is_readonly_inside_loop_body( - self, - dep: Dependency, - root_loop: Node, - children_cus: Sequence[Node], - children_loops: Sequence[Node], - loops_start_lines: Optional[List[LineID]] = None, - ) -> bool: - """Checks, whether a variable is read-only in loop body - - :param dep: dependency variable - :param root_loop: root loop - :return: true if variable is read-only in loop body - """ - if loops_start_lines is None: - loops_start_lines = [v.start_position() for v in children_loops] - - for v in children_cus: - for t, d in [ - (t, d) - for s, t, d in self.out_edges(v.id, EdgeType.DATA) - if d.dtype == DepType.WAR or d.dtype == DepType.WAW - ]: - # If there is a waw dependency for var, then var is written in loop - # (sink is always inside loop for waw/war) - if dep.memory_region == d.memory_region and not (d.sink_line in loops_start_lines): - return False - for t, d in [(t, d) for s, t, d in self.in_edges(v.id, EdgeType.DATA) if d.dtype == DepType.RAW]: - # If there is a reverse raw dependency for var, then var is written in loop - # (source is always inside loop for reverse raw) - if dep.memory_region == d.memory_region and not (d.source_line in loops_start_lines): - return False - return True - - def get_parent_function(self, node: Node) -> FunctionNode: - """Finds the parent of a node - - :param node: current node - :return: node of parent function - """ - if isinstance(node, FunctionNode): - return node - if node.parent_function_id is None: - # no precalculated information found. - current_node = node - parent_node: Optional[Node] = node - while parent_node is not None: - current_node = parent_node - if type(self.node_at(current_node.id)) == FunctionNode: - node.parent_function_id = current_node.id - break - parents = [e[0] for e in self.in_edges(current_node.id, etype=EdgeType.CHILD)] - if len(parents) == 0: - parent_node = None - else: - parent_node = self.node_at(parents[0]) - - assert node.parent_function_id - return cast(FunctionNode, self.node_at(node.parent_function_id)) - - def get_left_right_subtree( - self, target: Node, right_subtree: bool, ignore_called_nodes: bool = False - ) -> List[Node]: - """Searches for all subnodes of main which are to the left or to the right of the specified node - - :param target: node that divides the tree - :param right_subtree: true - right subtree, false - left subtree - :return: list of nodes in the subtree - """ - stack: List[Node] = [] - res: List[Node] = [] - visited = set() - - parent_func = self.get_parent_function(target) - stack.append(parent_func) - - while stack: - current = stack.pop() - - if current == target: - return res - if isinstance(current, CUNode): - res.append(current) - - if current in visited: # suppress looping - continue - else: - visited.add(current) - - if not ignore_called_nodes: - stack.extend( - self.direct_children_or_called_nodes(current) - if right_subtree - else reversed(self.direct_children_or_called_nodes(current)) - ) - else: - stack.extend( - self.direct_children(current) if right_subtree else reversed(self.direct_children(current)) - ) - return res - def path(self, source: Node, target: Node) -> List[Node]: """DFS from source to target over edges of child type @@ -1029,212 +540,9 @@ def __path_rec(self, source: Node, target: Node, visited: Set[Node]) -> List[Nod if source == target: return [source] - for child in [c for c in self.direct_children_or_called_nodes(source) if c not in visited]: + for child in [c for c in direct_children_or_called_nodes(self, source) if c not in visited]: path = self.__path_rec(child, target, visited) if path: path.insert(0, source) return path return [] - - def get_reduction_sign(self, line: str, name: str) -> str: - """Returns reduction operation for variable - - :param line: loop line number - :param name: variable name - :return: reduction operation - """ - for rv in self.reduction_vars: - if rv["loop_line"] == line and rv["name"] == name: - return rv["operation"] - return "" - - def dump_to_pickled_json(self) -> str: - """Encodes and returns the entire Object into a pickled json string. - The encoded string can be reconstructed into an object by using: - jsonpickle.decode(json_str) - - :return: encoded string - """ - return cast(str, jsonpickle.encode(self)) - - def check_reachability(self, target: Node, source: Node, edge_types: List[EdgeType]) -> bool: - """check if target is reachable from source via edges of types edge_type. - :param pet: PET graph - :param source: CUNode - :param target: CUNode - :param edge_types: List[EdgeType] - :return: Boolean""" - if source == target: - return True - visited: List[str] = [] - queue = [target] - while len(queue) > 0: - cur_node = queue.pop(0) - visited.append(cur_node.id) - tmp_list = [ - (s, t, e) for s, t, e in self.in_edges(cur_node.id) if s not in visited and e.etype in edge_types - ] - for e in tmp_list: - if self.node_at(e[0]) == source: - return True - else: - if e[0] not in visited: - queue.append(self.node_at(e[0])) - return False - - def is_predecessor(self, source_id: NodeID, target_id: NodeID) -> bool: - """returns true, if source is a predecessor of target. - This analysis includes traversal of successor, child and calls edges.""" - # if source and target_id are located within differenct functions, consider the callees instead of source_id - source_parent_function = self.get_parent_function(self.node_at(source_id)) - target_parent_function = self.get_parent_function(self.node_at(target_id)) - if source_parent_function != target_parent_function: - for callee_id in [s for s, _, _ in self.in_edges(source_parent_function.id, EdgeType.CALLSNODE)]: - if self.is_predecessor(callee_id, target_id): - return True - - # if target is a loop node, get the first child of the loop, i.e. the entry node into the loop - target_node = self.node_at(target_id) - if target_node.type == NodeType.LOOP: - target_id = self.direct_children(target_node)[0].id - - # perform a bfs search for target - queue: List[NodeID] = [source_id] - visited: List[NodeID] = [] - while queue: - current = queue.pop(0) - if current == target_id: - return True - visited.append(current) - # add direct successors to queue - queue += [ - n.id for n in self.direct_successors(self.node_at(current)) if n.id not in visited and n.id not in queue - ] - # add children to queue - queue += [ - n.id for n in self.direct_children(self.node_at(current)) if n.id not in visited and n.id not in queue - ] - # add called functions to queue - queue += [ - t for _, t, _ in self.out_edges(current, EdgeType.CALLSNODE) if t not in visited and t not in queue - ] - return False - - def check_reachability_and_get_path_nodes( - self, target: CUNode, source: CUNode, edge_types: List[EdgeType] - ) -> Tuple[bool, List[CUNode]]: - """check if target is reachable from source via edges of types edge_type. - :param pet: PET graph - :param source: CUNode - :param target: CUNode - :param edge_types: List[EdgeType] - :return: Boolean""" - if source == target: - return True, [] - - # trivially not reachable - if ( - self.get_parent_function(target) != self.get_parent_function(source) - and EdgeType.CALLSNODE not in edge_types - ): - print("TRIVIAL FALSE!: ", source, target) - return False, [] - - visited: List[NodeID] = [] - queue: List[Tuple[CUNode, List[CUNode]]] = [(target, [])] - while len(queue) > 0: - cur_node, cur_path = queue.pop(0) - visited.append(cur_node.id) - tmp_list = [ - (s, t, e) for s, t, e in self.in_edges(cur_node.id) if s not in visited and e.etype in edge_types - ] - for e in tmp_list: - if self.node_at(e[0]) == source: - return True, cur_path - else: - if e[0] not in visited: - tmp_path = copy.deepcopy(cur_path) - tmp_path.append(cur_node) - queue.append((cast(CUNode, self.node_at(e[0])), tmp_path)) - return False, [] - - def dump_to_gephi_file(self, name: str = "pet.gexf") -> None: - """Note: Destroys the PETGraph!""" - # replace node data with label - for node_id in self.g.nodes: - tmp_cu = self.g.nodes[node_id]["data"] - del self.g.nodes[node_id]["data"] - self.g.nodes[node_id]["id"] = tmp_cu.id - self.g.nodes[node_id]["type"] = str(tmp_cu.type) - for edge in self.g.edges: - dep: Dependency = self.g.edges[edge]["data"] - del self.g.edges[edge]["data"] - self.g.edges[edge]["edge_type"] = str(dep.etype.name) - if dep.etype == EdgeType.DATA: - self.g.edges[edge]["var"] = dep.var_name - if dep.dtype is None: - raise ValueError("dep.dtype has no type name!") - self.g.edges[edge]["dep_type"] = str(dep.dtype.name) - nx.write_gexf(self.g, name) - - def get_variable(self, root_node_id: NodeID, var_name: str) -> Optional[Variable]: - """Search for the type of the given variable by BFS searching through successor edges in reverse, starting from - the given root node, and checking the global and local vars of each encountered CU node.""" - queue: List[NodeID] = [root_node_id] - visited: Set[NodeID] = set() - while queue: - current = queue.pop(0) - current_node = cast(CUNode, self.node_at(current)) - visited.add(current) - variables = current_node.local_vars + current_node.global_vars - for v in variables: - if v.name == var_name: - return v - # add predecessors of current to the list - predecessors = [s for s, t, d in self.in_edges(current, EdgeType.SUCCESSOR)] - for pred in predecessors: - if pred not in visited and pred not in queue: - queue.append(pred) - return None - - def get_memory_regions(self, nodes: List[CUNode], var_name: str) -> Set[MemoryRegion]: - """check dependencies of nodes for usages of 'var_name' and extract memory regions related to this name""" - mem_regs: Set[MemoryRegion] = set() - for node in nodes: - out_deps = self.out_edges(node.id, EdgeType.DATA) - for s, t, d in out_deps: - if d.var_name == var_name: - if d.memory_region is not None: - mem_regs.add(d.memory_region) - return mem_regs - - def get_path_nodes_between(self, target: CUNode, source: CUNode, edge_types: List[EdgeType]) -> List[CUNode]: - """get all nodes of all patch which allow reaching target from source via edges of types edge_type. - :param pet: PET graph - :param source: CUNode - :param target: CUNode - :param edge_types: List[EdgeType] - :return: List of encountered nodes""" - - visited: List[NodeID] = [] - queue: List[Tuple[CUNode, List[CUNode]]] = [ - (cast(CUNode, self.node_at(t)), []) - for s, t, d in self.out_edges(source.id, edge_types) - if type(self.node_at(t)) == CUNode - ] - - while len(queue) > 0: - cur_node, cur_path = queue.pop(0) - visited.append(cur_node.id) - tmp_list = [ - (s, t, e) for s, t, e in self.out_edges(cur_node.id) if t not in visited and e.etype in edge_types - ] - for e in tmp_list: - if self.node_at(e[1]) == target or self.node_at(e[1]) == source: - continue - else: - if e[1] not in visited: - tmp_path = copy.deepcopy(cur_path) - tmp_path.append(cur_node) - queue.append((cast(CUNode, self.node_at(e[1])), tmp_path)) - return [cast(CUNode, self.node_at(nid)) for nid in set(visited)] diff --git a/discopop_explorer/discopop_explorer.py b/discopop_explorer/discopop_explorer.py index 40bce76e9..d9fd4aa0a 100644 --- a/discopop_explorer/discopop_explorer.py +++ b/discopop_explorer/discopop_explorer.py @@ -18,6 +18,7 @@ import pstats2 # type:ignore from pluginbase import PluginBase # type: ignore +from discopop_explorer.functions.PEGraph.output.json import dump_to_pickled_json from discopop_library.ArgumentClasses.GeneralArguments import GeneralArguments # type: ignore from discopop_library.HostpotLoader.HotspotLoaderArguments import HotspotLoaderArguments from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType @@ -246,7 +247,7 @@ def run(arguments: ExplorerArguments) -> None: if arguments.enable_pet_dump_file is not None: with open(arguments.enable_pet_dump_file, "w+") as f: - f.write(res.pet.dump_to_pickled_json()) + f.write(dump_to_pickled_json(res.pet)) f.flush() f.close() diff --git a/discopop_explorer/functions/PEGraph/__init__.py b/discopop_explorer/functions/PEGraph/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/discopop_explorer/functions/PEGraph/output/gephi.py b/discopop_explorer/functions/PEGraph/output/gephi.py new file mode 100644 index 000000000..7eb231215 --- /dev/null +++ b/discopop_explorer/functions/PEGraph/output/gephi.py @@ -0,0 +1,32 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from discopop_explorer.classes.PEGraph.Dependency import Dependency +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX +from discopop_explorer.enums.EdgeType import EdgeType +import networkx as nx # type: ignore + + +def dump_to_gephi_file(pet: PEGraphX, name: str = "pet.gexf") -> None: + """Note: Destroys the PETGraph!""" + # replace node data with label + for node_id in pet.g.nodes: + tmp_cu = pet.g.nodes[node_id]["data"] + del pet.g.nodes[node_id]["data"] + pet.g.nodes[node_id]["id"] = tmp_cu.id + pet.g.nodes[node_id]["type"] = str(tmp_cu.type) + for edge in pet.g.edges: + dep: Dependency = pet.g.edges[edge]["data"] + del pet.g.edges[edge]["data"] + pet.g.edges[edge]["edge_type"] = str(dep.etype.name) + if dep.etype == EdgeType.DATA: + pet.g.edges[edge]["var"] = dep.var_name + if dep.dtype is None: + raise ValueError("dep.dtype has no type name!") + pet.g.edges[edge]["dep_type"] = str(dep.dtype.name) + nx.write_gexf(pet.g, name) diff --git a/discopop_explorer/functions/PEGraph/output/json.py b/discopop_explorer/functions/PEGraph/output/json.py new file mode 100644 index 000000000..8f4400996 --- /dev/null +++ b/discopop_explorer/functions/PEGraph/output/json.py @@ -0,0 +1,23 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from typing import cast + +import jsonpickle # type: ignore + +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX + + +def dump_to_pickled_json(self: PEGraphX) -> str: + """Encodes and returns the entire Object into a pickled json string. + The encoded string can be reconstructed into an object by using: + jsonpickle.decode(json_str) + + :return: encoded string + """ + return cast(str, jsonpickle.encode(self)) diff --git a/discopop_explorer/functions/PEGraph/properties/check_reachability.py b/discopop_explorer/functions/PEGraph/properties/check_reachability.py new file mode 100644 index 000000000..00644be6c --- /dev/null +++ b/discopop_explorer/functions/PEGraph/properties/check_reachability.py @@ -0,0 +1,37 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from typing import List +from discopop_explorer.classes.PEGraph.Node import Node +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.queries.edges import in_edges + + +def check_reachability(pet: PEGraphX, target: Node, source: Node, edge_types: List[EdgeType]) -> bool: + """check if target is reachable from source via edges of types edge_type. + :param pet: PET graph + :param source: CUNode + :param target: CUNode + :param edge_types: List[EdgeType] + :return: Boolean""" + if source == target: + return True + visited: List[str] = [] + queue = [target] + while len(queue) > 0: + cur_node = queue.pop(0) + visited.append(cur_node.id) + tmp_list = [(s, t, e) for s, t, e in in_edges(pet, cur_node.id) if s not in visited and e.etype in edge_types] + for e in tmp_list: + if pet.node_at(e[0]) == source: + return True + else: + if e[0] not in visited: + queue.append(pet.node_at(e[0])) + return False diff --git a/discopop_explorer/functions/PEGraph/properties/depends_ignore_readonly.py b/discopop_explorer/functions/PEGraph/properties/depends_ignore_readonly.py new file mode 100644 index 000000000..d000d478c --- /dev/null +++ b/discopop_explorer/functions/PEGraph/properties/depends_ignore_readonly.py @@ -0,0 +1,75 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from typing import List +from discopop_explorer.aliases.LineID import LineID +from discopop_explorer.classes.PEGraph.CUNode import CUNode +from discopop_explorer.classes.PEGraph.LoopNode import LoopNode +from discopop_explorer.classes.PEGraph.Node import Node +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX +from discopop_explorer.enums.DepType import DepType +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.properties.is_loop_index import is_loop_index +from discopop_explorer.functions.PEGraph.properties.is_readonly_inside_loop_body import is_readonly_inside_loop_body +from discopop_explorer.functions.PEGraph.queries.edges import out_edges +from discopop_explorer.functions.PEGraph.queries.subtree import subtree_of_type + + +def depends_ignore_readonly(self: PEGraphX, source: Node, target: Node, root_loop: Node) -> bool: + """Detects if source node or one of it's children has a RAW dependency to target node or one of it's children + The loop index and readonly variables are ignored. + + :param source: source node for dependency detection (later occurrence in the source code) + :param target: target of dependency (prior occurrence in the source code) + :param root_loop: root loop + :return: true, if there is RAW dependency""" + if source == target: + return False + + # get recursive children of source and target + source_children_ids = [node.id for node in subtree_of_type(self, source, CUNode)] + target_children_ids = [node.id for node in subtree_of_type(self, target, CUNode)] + + # get required metadata + loop_start_lines: List[LineID] = [] + root_children = subtree_of_type(self, root_loop, (CUNode, LoopNode)) + root_children_cus = [cu for cu in root_children if isinstance(cu, CUNode)] + root_children_loops = [cu for cu in root_children if isinstance(cu, LoopNode)] + for v in root_children_loops: + loop_start_lines.append(v.start_position()) + + # check for RAW dependencies between any of source_children and any of target_children + for source_child_id in source_children_ids: + # get a list of filtered dependencies, outgoing from source_child + out_deps = out_edges(self, source_child_id, EdgeType.DATA) + out_raw_deps = [dep for dep in out_deps if dep[2].dtype == DepType.RAW] + filtered_deps = [ + elem + for elem in out_raw_deps + if not is_readonly_inside_loop_body( + self, + elem[2], + root_loop, + root_children_cus, + root_children_loops, + loops_start_lines=loop_start_lines, + ) + ] + filtered_deps = [ + elem + for elem in filtered_deps + if not is_loop_index(self, elem[2].var_name, loop_start_lines, root_children_cus) + ] + # get a list of dependency targets + dep_targets = [t for _, t, _ in filtered_deps] + # check if overlap between dependency targets and target_children exists. + overlap = [node_id for node_id in dep_targets if node_id in target_children_ids] + if len(overlap) > 0: + # if so, a RAW dependency exists + return True + return False diff --git a/discopop_explorer/functions/PEGraph/properties/is_loop_index.py b/discopop_explorer/functions/PEGraph/properties/is_loop_index.py new file mode 100644 index 000000000..ed188f2ce --- /dev/null +++ b/discopop_explorer/functions/PEGraph/properties/is_loop_index.py @@ -0,0 +1,44 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. +from __future__ import annotations +from typing import TYPE_CHECKING, List, Optional, Sequence + +from discopop_explorer.aliases.LineID import LineID +from discopop_explorer.classes.PEGraph.Node import Node + +if TYPE_CHECKING: + from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX +from discopop_explorer.enums.DepType import DepType +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.queries.edges import out_edges + + +def is_loop_index( + pet: PEGraphX, var_name: Optional[str], loops_start_lines: List[LineID], children: Sequence[Node] +) -> bool: + """Checks, whether the variable is a loop index. + + :param var_name: name of the variable + :param loops_start_lines: start lines of the loops + :param children: children nodes of the loops + :return: true if edge represents loop index + """ + + # If there is a raw dependency for var, the source cu is part of the loop + # and the dependency occurs in loop header, then var is loop index+ + + for c in children: + for t, d in [ + (t, d) + for s, t, d in out_edges(pet, c.id, EdgeType.DATA) + if d.dtype == DepType.RAW and d.var_name == var_name + ]: + if d.sink_line == d.source_line and d.source_line in loops_start_lines and pet.node_at(t) in children: + return True + + return False diff --git a/discopop_explorer/functions/PEGraph/properties/is_passed_by_reference.py b/discopop_explorer/functions/PEGraph/properties/is_passed_by_reference.py new file mode 100644 index 000000000..0e987f6c8 --- /dev/null +++ b/discopop_explorer/functions/PEGraph/properties/is_passed_by_reference.py @@ -0,0 +1,20 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from discopop_explorer.classes.PEGraph.Dependency import Dependency +from discopop_explorer.classes.PEGraph.FunctionNode import FunctionNode +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX + + +def is_passed_by_reference(pet: PEGraphX, dep: Dependency, func: FunctionNode) -> bool: + res = False + + for i in func.args: + if i.name == dep.var_name: + return True + return False diff --git a/discopop_explorer/functions/PEGraph/properties/is_predecessor.py b/discopop_explorer/functions/PEGraph/properties/is_predecessor.py new file mode 100644 index 000000000..c5ac2fb3f --- /dev/null +++ b/discopop_explorer/functions/PEGraph/properties/is_predecessor.py @@ -0,0 +1,52 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from typing import List +from discopop_explorer.aliases.NodeID import NodeID +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.enums.NodeType import NodeType +from discopop_explorer.functions.PEGraph.queries.edges import in_edges, out_edges +from discopop_explorer.functions.PEGraph.traversal.children import direct_children +from discopop_explorer.functions.PEGraph.traversal.parent import get_parent_function +from discopop_explorer.functions.PEGraph.traversal.successors import direct_successors + + +def is_predecessor(pet: PEGraphX, source_id: NodeID, target_id: NodeID) -> bool: + """returns true, if source is a predecessor of target. + This analysis includes traversal of successor, child and calls edges.""" + # if source and target_id are located within differenct functions, consider the callees instead of source_id + source_parent_function = get_parent_function(pet, pet.node_at(source_id)) + target_parent_function = get_parent_function(pet, pet.node_at(target_id)) + if source_parent_function != target_parent_function: + for callee_id in [s for s, _, _ in in_edges(pet, source_parent_function.id, EdgeType.CALLSNODE)]: + if is_predecessor(pet, callee_id, target_id): + return True + + # if target is a loop node, get the first child of the loop, i.e. the entry node into the loop + target_node = pet.node_at(target_id) + if target_node.type == NodeType.LOOP: + target_id = direct_children(pet, target_node)[0].id + + # perform a bfs search for target + queue: List[NodeID] = [source_id] + visited: List[NodeID] = [] + while queue: + current = queue.pop(0) + if current == target_id: + return True + visited.append(current) + # add direct successors to queue + queue += [ + n.id for n in direct_successors(pet, pet.node_at(current)) if n.id not in visited and n.id not in queue + ] + # add children to queue + queue += [n.id for n in direct_children(pet, pet.node_at(current)) if n.id not in visited and n.id not in queue] + # add called functions to queue + queue += [t for _, t, _ in out_edges(pet, current, EdgeType.CALLSNODE) if t not in visited and t not in queue] + return False diff --git a/discopop_explorer/functions/PEGraph/properties/is_readonly_inside_loop_body.py b/discopop_explorer/functions/PEGraph/properties/is_readonly_inside_loop_body.py new file mode 100644 index 000000000..404104c1a --- /dev/null +++ b/discopop_explorer/functions/PEGraph/properties/is_readonly_inside_loop_body.py @@ -0,0 +1,53 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. +from __future__ import annotations +from typing import TYPE_CHECKING, List, Optional, Sequence +from discopop_explorer.aliases.LineID import LineID +from discopop_explorer.classes.PEGraph.Dependency import Dependency +from discopop_explorer.classes.PEGraph.Node import Node + +if TYPE_CHECKING: + from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX +from discopop_explorer.enums.DepType import DepType +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.queries.edges import in_edges, out_edges + + +def is_readonly_inside_loop_body( + pet: PEGraphX, + dep: Dependency, + root_loop: Node, + children_cus: Sequence[Node], + children_loops: Sequence[Node], + loops_start_lines: Optional[List[LineID]] = None, +) -> bool: + """Checks, whether a variable is read-only in loop body + + :param dep: dependency variable + :param root_loop: root loop + :return: true if variable is read-only in loop body + """ + if loops_start_lines is None: + loops_start_lines = [v.start_position() for v in children_loops] + + for v in children_cus: + for t, d in [ + (t, d) + for s, t, d in out_edges(pet, v.id, EdgeType.DATA) + if d.dtype == DepType.WAR or d.dtype == DepType.WAW + ]: + # If there is a waw dependency for var, then var is written in loop + # (sink is always inside loop for waw/war) + if dep.memory_region == d.memory_region and not (d.sink_line in loops_start_lines): + return False + for t, d in [(t, d) for s, t, d in in_edges(pet, v.id, EdgeType.DATA) if d.dtype == DepType.RAW]: + # If there is a reverse raw dependency for var, then var is written in loop + # (source is always inside loop for reverse raw) + if dep.memory_region == d.memory_region and not (d.source_line in loops_start_lines): + return False + return True diff --git a/discopop_explorer/functions/PEGraph/properties/is_reduction_var_by_name.py b/discopop_explorer/functions/PEGraph/properties/is_reduction_var_by_name.py new file mode 100644 index 000000000..690b8a47e --- /dev/null +++ b/discopop_explorer/functions/PEGraph/properties/is_reduction_var_by_name.py @@ -0,0 +1,23 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. +from __future__ import annotations +from typing import TYPE_CHECKING +from discopop_explorer.aliases.LineID import LineID + +if TYPE_CHECKING: + from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX + + +def is_reduction_var_by_name(self: PEGraphX, line: LineID, name: str) -> bool: + """Determines, whether or not the given variable is reduction variable + + :param line: loop line number + :param name: variable name + :return: true if is reduction variable + """ + return any(rv for rv in self.reduction_vars if rv["loop_line"] == line and rv["name"] == name) diff --git a/discopop_explorer/functions/PEGraph/properties/is_scalar_val.py b/discopop_explorer/functions/PEGraph/properties/is_scalar_val.py new file mode 100644 index 000000000..38bebc267 --- /dev/null +++ b/discopop_explorer/functions/PEGraph/properties/is_scalar_val.py @@ -0,0 +1,25 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from typing import List +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX +from discopop_explorer.classes.variable import Variable + + +def is_scalar_val(pet: PEGraphX, allVars: List[Variable], var: str) -> bool: + """Checks if variable is a scalar value + + :param var: variable + :return: true if scalar + """ + for x in allVars: + if x.name == var: + return not (x.type.endswith("**") or x.type.startswith("ARRAY") or x.type.startswith("[")) + else: + return False + raise ValueError("allVars must not be empty.") diff --git a/discopop_explorer/functions/PEGraph/queries/edges.py b/discopop_explorer/functions/PEGraph/queries/edges.py new file mode 100644 index 000000000..36ad56e3c --- /dev/null +++ b/discopop_explorer/functions/PEGraph/queries/edges.py @@ -0,0 +1,49 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. +from __future__ import annotations +from typing import TYPE_CHECKING, List, Optional, Tuple, Union +from discopop_explorer.aliases.NodeID import NodeID +from discopop_explorer.classes.PEGraph.Dependency import Dependency + +if TYPE_CHECKING: + from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX + from discopop_explorer.enums.EdgeType import EdgeType + + +def in_edges( + pet: PEGraphX, node_id: NodeID, etype: Optional[Union[EdgeType, List[EdgeType]]] = None +) -> List[Tuple[NodeID, NodeID, Dependency]]: + """Get incoming edges of node of specified type + + :param node_id: id of the target node + :param etype: type of edges + :return: list of incoming edges + """ + if etype is None: + return [t for t in pet.g.in_edges(node_id, data="data")] + elif type(etype) == list: + return [t for t in pet.g.in_edges(node_id, data="data") if t[2].etype in etype] + else: + return [t for t in pet.g.in_edges(node_id, data="data") if t[2].etype == etype] + + +def out_edges( + pet: PEGraphX, node_id: NodeID, etype: Optional[Union[EdgeType, List[EdgeType]]] = None +) -> List[Tuple[NodeID, NodeID, Dependency]]: + """Get outgoing edges of node of specified type + + :param node_id: id of the source node + :param etype: type of edges + :return: list of outgoing edges + """ + if etype is None: + return [t for t in pet.g.out_edges(node_id, data="data")] + elif type(etype) == list: + return [t for t in pet.g.out_edges(node_id, data="data") if t[2].etype in etype] + else: + return [t for t in pet.g.out_edges(node_id, data="data") if t[2].etype == etype] diff --git a/discopop_explorer/functions/PEGraph/queries/memory_regions.py b/discopop_explorer/functions/PEGraph/queries/memory_regions.py new file mode 100644 index 000000000..a7b63348a --- /dev/null +++ b/discopop_explorer/functions/PEGraph/queries/memory_regions.py @@ -0,0 +1,26 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from typing import List, Set +from discopop_explorer.aliases.MemoryRegion import MemoryRegion +from discopop_explorer.classes.PEGraph.CUNode import CUNode +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.queries.edges import out_edges + + +def get_memory_regions(pet: PEGraphX, nodes: List[CUNode], var_name: str) -> Set[MemoryRegion]: + """check dependencies of nodes for usages of 'var_name' and extract memory regions related to this name""" + mem_regs: Set[MemoryRegion] = set() + for node in nodes: + out_deps = out_edges(pet, node.id, EdgeType.DATA) + for s, t, d in out_deps: + if d.var_name == var_name: + if d.memory_region is not None: + mem_regs.add(d.memory_region) + return mem_regs diff --git a/discopop_explorer/functions/PEGraph/queries/nodes.py b/discopop_explorer/functions/PEGraph/queries/nodes.py new file mode 100644 index 000000000..26bd6cf50 --- /dev/null +++ b/discopop_explorer/functions/PEGraph/queries/nodes.py @@ -0,0 +1,34 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. +from __future__ import annotations +from typing import TYPE_CHECKING, Any, List, Tuple, Type, Union, overload + +from discopop_explorer.classes.PEGraph.Node import Node +from discopop_explorer.classes.PEGraph.NodeT import NodeT + +if TYPE_CHECKING: + from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX + + +@overload +def all_nodes(pet: PEGraphX) -> List[Node]: + ... + + +@overload +def all_nodes(pet: PEGraphX, type: Union[Type[NodeT], Tuple[Type[NodeT], ...]]) -> List[NodeT]: + ... + + +def all_nodes(pet: PEGraphX, type: Any = Node) -> List[NodeT]: + """List of all nodes of specified type + + :param type: type(s) of nodes + :return: List of all nodes + """ + return [n[1] for n in pet.g.nodes(data="data") if isinstance(n[1], type)] diff --git a/discopop_explorer/functions/PEGraph/queries/paths.py b/discopop_explorer/functions/PEGraph/queries/paths.py new file mode 100644 index 000000000..710c01935 --- /dev/null +++ b/discopop_explorer/functions/PEGraph/queries/paths.py @@ -0,0 +1,80 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +import copy +from typing import List, Tuple, cast +from discopop_explorer.aliases.NodeID import NodeID +from discopop_explorer.classes.PEGraph.CUNode import CUNode +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.queries.edges import in_edges, out_edges +from discopop_explorer.functions.PEGraph.traversal.parent import get_parent_function + + +def check_reachability_and_get_path_nodes( + pet: PEGraphX, target: CUNode, source: CUNode, edge_types: List[EdgeType] +) -> Tuple[bool, List[CUNode]]: + """check if target is reachable from source via edges of types edge_type. + :param pet: PET graph + :param source: CUNode + :param target: CUNode + :param edge_types: List[EdgeType] + :return: Boolean""" + if source == target: + return True, [] + + # trivially not reachable + if get_parent_function(pet, target) != get_parent_function(pet, source) and EdgeType.CALLSNODE not in edge_types: + print("TRIVIAL FALSE!: ", source, target) + return False, [] + + visited: List[NodeID] = [] + queue: List[Tuple[CUNode, List[CUNode]]] = [(target, [])] + while len(queue) > 0: + cur_node, cur_path = queue.pop(0) + visited.append(cur_node.id) + tmp_list = [(s, t, e) for s, t, e in in_edges(pet, cur_node.id) if s not in visited and e.etype in edge_types] + for e in tmp_list: + if pet.node_at(e[0]) == source: + return True, cur_path + else: + if e[0] not in visited: + tmp_path = copy.deepcopy(cur_path) + tmp_path.append(cur_node) + queue.append((cast(CUNode, pet.node_at(e[0])), tmp_path)) + return False, [] + + +def get_path_nodes_between(pet: PEGraphX, target: CUNode, source: CUNode, edge_types: List[EdgeType]) -> List[CUNode]: + """get all nodes of all patch which allow reaching target from source via edges of types edge_type. + :param pet: PET graph + :param source: CUNode + :param target: CUNode + :param edge_types: List[EdgeType] + :return: List of encountered nodes""" + + visited: List[NodeID] = [] + queue: List[Tuple[CUNode, List[CUNode]]] = [ + (cast(CUNode, pet.node_at(t)), []) + for s, t, d in out_edges(pet, source.id, edge_types) + if type(pet.node_at(t)) == CUNode + ] + + while len(queue) > 0: + cur_node, cur_path = queue.pop(0) + visited.append(cur_node.id) + tmp_list = [(s, t, e) for s, t, e in out_edges(pet, cur_node.id) if t not in visited and e.etype in edge_types] + for e in tmp_list: + if pet.node_at(e[1]) == target or pet.node_at(e[1]) == source: + continue + else: + if e[1] not in visited: + tmp_path = copy.deepcopy(cur_path) + tmp_path.append(cur_node) + queue.append((cast(CUNode, pet.node_at(e[1])), tmp_path)) + return [cast(CUNode, pet.node_at(nid)) for nid in set(visited)] diff --git a/discopop_explorer/functions/PEGraph/queries/reductions.py b/discopop_explorer/functions/PEGraph/queries/reductions.py new file mode 100644 index 000000000..7bade2916 --- /dev/null +++ b/discopop_explorer/functions/PEGraph/queries/reductions.py @@ -0,0 +1,22 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX + + +def get_reduction_sign(pet: PEGraphX, line: str, name: str) -> str: + """Returns reduction operation for variable + + :param line: loop line number + :param name: variable name + :return: reduction operation + """ + for rv in pet.reduction_vars: + if rv["loop_line"] == line and rv["name"] == name: + return rv["operation"] + return "" diff --git a/discopop_explorer/functions/PEGraph/queries/subtree.py b/discopop_explorer/functions/PEGraph/queries/subtree.py new file mode 100644 index 000000000..87468370c --- /dev/null +++ b/discopop_explorer/functions/PEGraph/queries/subtree.py @@ -0,0 +1,111 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. +from __future__ import annotations +from typing import TYPE_CHECKING, Any, List, Set, Tuple, Type, Union, overload +from discopop_explorer.classes.PEGraph.CUNode import CUNode +from discopop_explorer.classes.PEGraph.Node import Node +from discopop_explorer.classes.PEGraph.NodeT import NodeT + +if TYPE_CHECKING: + from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.queries.edges import out_edges +from discopop_explorer.functions.PEGraph.traversal.children import direct_children, direct_children_or_called_nodes +from discopop_explorer.functions.PEGraph.traversal.parent import get_parent_function + + +def get_left_right_subtree( + self: PEGraphX, target: Node, right_subtree: bool, ignore_called_nodes: bool = False +) -> List[Node]: + """Searches for all subnodes of main which are to the left or to the right of the specified node + + :param target: node that divides the tree + :param right_subtree: true - right subtree, false - left subtree + :return: list of nodes in the subtree + """ + stack: List[Node] = [] + res: List[Node] = [] + visited = set() + + parent_func = get_parent_function(self, target) + stack.append(parent_func) + + while stack: + current = stack.pop() + + if current == target: + return res + if isinstance(current, CUNode): + res.append(current) + + if current in visited: # suppress looping + continue + else: + visited.add(current) + + if not ignore_called_nodes: + stack.extend( + direct_children_or_called_nodes(self, current) + if right_subtree + else reversed(direct_children_or_called_nodes(self, current)) + ) + else: + stack.extend(direct_children(self, current) if right_subtree else reversed(direct_children(self, current))) + return res + + +@overload +def subtree_of_type(pet: PEGraphX, root: Node) -> List[Node]: + ... + + +@overload +def subtree_of_type(pet: PEGraphX, root: Node, type: Union[Type[NodeT], Tuple[Type[NodeT], ...]]) -> List[NodeT]: + ... + + +def subtree_of_type(pet: PEGraphX, root: Node, type: Any = Node) -> List[NodeT]: + """Gets all nodes in subtree of specified type including root + + :param root: root node + :param type: type of children, None is equal to a wildcard + :return: list of nodes in subtree + """ + return subtree_of_type_rec(pet, root, set(), type) + + +@overload +def subtree_of_type_rec(pet: PEGraphX, root: Node, visited: Set[Node]) -> List[Node]: + ... + + +@overload +def subtree_of_type_rec( + pet: PEGraphX, root: Node, visited: Set[Node], type: Union[Type[NodeT], Tuple[Type[NodeT], ...]] +) -> List[NodeT]: + ... + + +def subtree_of_type_rec(pet: PEGraphX, root: Node, visited: Set[Node], type: Any = Node) -> List[NodeT]: + """recursive helper function for subtree_of_type""" + # check if root is of type target + res = [] + if isinstance(root, type): + res.append(root) + + # append root to visited + visited.add(root) + + # enter recursion + for _, target, _ in out_edges(pet, root.id, [EdgeType.CHILD, EdgeType.CALLSNODE]): + # prevent cycles + if pet.node_at(target) in visited: + continue + res += subtree_of_type_rec(pet, pet.node_at(target), visited, type) + + return res diff --git a/discopop_explorer/functions/PEGraph/queries/variables.py b/discopop_explorer/functions/PEGraph/queries/variables.py new file mode 100644 index 000000000..6e77d5bfc --- /dev/null +++ b/discopop_explorer/functions/PEGraph/queries/variables.py @@ -0,0 +1,116 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. +from __future__ import annotations +from typing import TYPE_CHECKING, Dict, List, Optional, Sequence, Set, cast +from discopop_explorer.aliases.MemoryRegion import MemoryRegion +from discopop_explorer.aliases.NodeID import NodeID +from discopop_explorer.classes.PEGraph.CUNode import CUNode +from discopop_explorer.classes.PEGraph.Node import Node + +if TYPE_CHECKING: + from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX +from discopop_explorer.classes.variable import Variable +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.properties.is_reduction_var_by_name import is_reduction_var_by_name +from discopop_explorer.functions.PEGraph.queries.edges import in_edges, out_edges +from discopop_explorer.functions.PEGraph.queries.subtree import subtree_of_type + + +def get_variable(pet: PEGraphX, root_node_id: NodeID, var_name: str) -> Optional[Variable]: + """Search for the type of the given variable by BFS searching through successor edges in reverse, starting from + the given root node, and checking the global and local vars of each encountered CU node.""" + queue: List[NodeID] = [root_node_id] + visited: Set[NodeID] = set() + while queue: + current = queue.pop(0) + current_node = cast(CUNode, pet.node_at(current)) + visited.add(current) + variables = current_node.local_vars + current_node.global_vars + for v in variables: + if v.name == var_name: + return v + # add predecessors of current to the list + predecessors = [s for s, t, d in in_edges(pet, current, EdgeType.SUCCESSOR)] + for pred in predecessors: + if pred not in visited and pred not in queue: + queue.append(pred) + return None + + +def get_variables(pet: PEGraphX, nodes: Sequence[Node]) -> Dict[Variable, Set[MemoryRegion]]: + """Gets all variables and corresponding memory regions in nodes + + :param nodes: nodes + :return: Set of variables + """ + res: Dict[Variable, Set[MemoryRegion]] = dict() + for node in nodes: + if isinstance(node, CUNode): + for v in node.local_vars: + if v not in res: + res[v] = set() + for v in node.global_vars: + if v not in res: + res[v] = set() + # try to identify memory regions + for var_name in res: + # since the variable name is checked for equality afterwards, + # it is safe to consider incoming dependencies at this point as well. + # Note that INIT type edges are considered as well! + for _, _, dep in out_edges(pet, node.id, EdgeType.DATA) + in_edges(pet, node.id, EdgeType.DATA): + if dep.var_name == var_name.name: + if dep.memory_region is not None: + res[var_name].add(dep.memory_region) + return res + + +def get_undefined_variables_inside_loop( + pet: PEGraphX, root_loop: Node, include_global_vars: bool = False +) -> Dict[Variable, Set[MemoryRegion]]: + sub = subtree_of_type(pet, root_loop, CUNode) + vars = get_variables(pet, sub) + dummyVariables = [] + definedVarsInLoop = [] + definedVarsInCalledFunctions = [] + + # Remove llvm temporary variables + for var in vars: + if var.defLine == "LineNotFound" or "0:" in var.defLine: + dummyVariables.append(var) + elif not include_global_vars: + if var.defLine == "GlobalVar" and not is_reduction_var_by_name(pet, root_loop.start_position(), var.name): + dummyVariables.append(var) + + # vars = list(set(vars) ^ set(dummyVariables)) + for key in set(dummyVariables): + if key in vars: + del vars[key] + + # Exclude variables which are defined inside the loop + for var in vars: + if var.defLine >= root_loop.start_position() and var.defLine <= root_loop.end_position(): + definedVarsInLoop.append(var) + + # vars = list(set(vars) ^ set(definedVarsInLoop)) + for key in set(definedVarsInLoop): + if key in vars: + del vars[key] + + # Also, exclude variables which are defined inside + # functions that are called within the loop + for var in vars: + for s in sub: + if var.defLine >= s.start_position() and var.defLine <= s.end_position(): + definedVarsInCalledFunctions.append(var) + + # vars = list(set(vars) ^ set(definedVarsInCalledFunctions)) + for key in set(definedVarsInCalledFunctions): + if key in vars: + del vars[key] + + return vars diff --git a/discopop_explorer/functions/PEGraph/traversal/__init__.py b/discopop_explorer/functions/PEGraph/traversal/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/discopop_explorer/functions/PEGraph/traversal/children.py b/discopop_explorer/functions/PEGraph/traversal/children.py new file mode 100644 index 000000000..75fca3dff --- /dev/null +++ b/discopop_explorer/functions/PEGraph/traversal/children.py @@ -0,0 +1,48 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from __future__ import annotations +from typing import TYPE_CHECKING, List, Type + +from discopop_explorer.classes.PEGraph.NodeT import NodeT +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.queries.edges import out_edges + +if TYPE_CHECKING: + from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX + from discopop_explorer.classes.PEGraph.Node import Node + + +def direct_children_or_called_nodes(pet: PEGraphX, root: Node) -> List[Node]: + """Gets direct children of any type. Also includes nodes of called functions + + :param root: root node + :return: list of direct children + """ + return [pet.node_at(t) for s, t, d in out_edges(pet, root.id, [EdgeType.CHILD, EdgeType.CALLSNODE])] + + +def direct_children(pet: PEGraphX, root: Node) -> List[Node]: + """Gets direct children of any type. This includes called nodes! + + :param root: root node + :return: list of direct children + """ + return [pet.node_at(t) for s, t, d in out_edges(pet, root.id, EdgeType.CHILD)] + + +def direct_children_or_called_nodes_of_type(pet: PEGraphX, root: Node, type: Type[NodeT]) -> List[NodeT]: + """Gets only direct children of specified type. This includes called nodes! + + :param root: root node + :param type: type of children + :return: list of direct children + """ + nodes = [pet.node_at(t) for s, t, d in out_edges(pet, root.id, [EdgeType.CHILD, EdgeType.CALLSNODE])] + + return [t for t in nodes if isinstance(t, type)] diff --git a/discopop_explorer/functions/PEGraph/traversal/parent.py b/discopop_explorer/functions/PEGraph/traversal/parent.py new file mode 100644 index 000000000..5a4edc498 --- /dev/null +++ b/discopop_explorer/functions/PEGraph/traversal/parent.py @@ -0,0 +1,43 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. +from __future__ import annotations +from typing import TYPE_CHECKING, Optional, cast +from discopop_explorer.classes.PEGraph.FunctionNode import FunctionNode +from discopop_explorer.classes.PEGraph.Node import Node + +if TYPE_CHECKING: + from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.queries.edges import in_edges + + +def get_parent_function(pet: PEGraphX, node: Node) -> FunctionNode: + """Finds the parent of a node + + :param node: current node + :return: node of parent function + """ + if isinstance(node, FunctionNode): + return node + if node.parent_function_id is None: + # no precalculated information found. + current_node = node + parent_node: Optional[Node] = node + while parent_node is not None: + current_node = parent_node + if type(pet.node_at(current_node.id)) == FunctionNode: + node.parent_function_id = current_node.id + break + parents = [e[0] for e in in_edges(pet, current_node.id, etype=EdgeType.CHILD)] + if len(parents) == 0: + parent_node = None + else: + parent_node = pet.node_at(parents[0]) + + assert node.parent_function_id + return cast(FunctionNode, pet.node_at(node.parent_function_id)) diff --git a/discopop_explorer/functions/PEGraph/traversal/successors.py b/discopop_explorer/functions/PEGraph/traversal/successors.py new file mode 100644 index 000000000..439d20b9b --- /dev/null +++ b/discopop_explorer/functions/PEGraph/traversal/successors.py @@ -0,0 +1,27 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from __future__ import annotations +from typing import TYPE_CHECKING, List + +from discopop_explorer.functions.PEGraph.queries.edges import out_edges + +if TYPE_CHECKING: + from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX + from discopop_explorer.classes.PEGraph.Node import Node + +from discopop_explorer.enums.EdgeType import EdgeType + + +def direct_successors(pet: PEGraphX, root: Node) -> List[Node]: + """Gets only direct successors of any type + + :param root: root node + :return: list of direct successors + """ + return [pet.node_at(t) for s, t, d in out_edges(pet, root.id, EdgeType.SUCCESSOR)] diff --git a/discopop_explorer/functions/PEGraph/unused/__init__.py b/discopop_explorer/functions/PEGraph/unused/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/discopop_explorer/functions/PEGraph/unused/unused_functions.py b/discopop_explorer/functions/PEGraph/unused/unused_functions.py new file mode 100644 index 000000000..dae90c4d6 --- /dev/null +++ b/discopop_explorer/functions/PEGraph/unused/unused_functions.py @@ -0,0 +1,114 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +import itertools +from typing import List, Sequence, Set, cast +from discopop_explorer.aliases.NodeID import NodeID +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX +from discopop_explorer.classes.PEGraph.CUNode import CUNode +from discopop_explorer.classes.PEGraph.Dependency import Dependency +from discopop_explorer.classes.PEGraph.Node import Node +from discopop_explorer.classes.variable import Variable +from discopop_explorer.enums.DepType import DepType +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.properties.is_passed_by_reference import is_passed_by_reference +from discopop_explorer.functions.PEGraph.queries.edges import out_edges +from discopop_explorer.functions.PEGraph.queries.subtree import subtree_of_type +from discopop_explorer.functions.PEGraph.traversal.parent import get_parent_function + + +def unused_check_alias(pet: PEGraphX, s: NodeID, t: NodeID, d: Dependency, root_loop: Node) -> bool: + sub = subtree_of_type(pet, root_loop, CUNode) + parent_func_sink = get_parent_function(pet, pet.node_at(s)) + parent_func_source = get_parent_function(pet, pet.node_at(t)) + + res = False + d_var_name_str = cast(str, d.var_name) + + if unused_is_global(pet, d_var_name_str, sub) and not ( + is_passed_by_reference(pet, d, parent_func_sink) and is_passed_by_reference(pet, d, parent_func_source) + ): + return res + return not res + + +def unused_is_global(pet: PEGraphX, var: str, tree: Sequence[Node]) -> bool: + """Checks if variable is global + + :param var: variable name + :param tree: nodes to search + :return: true if global + """ + + for node in tree: + if isinstance(node, CUNode): + for gv in node.global_vars: + if gv.name == var: + # TODO from tmp global vars + return False + return False + + +def unused_get_first_written_vars_in_loop( + pet: PEGraphX, undefinedVarsInLoop: List[Variable], node: Node, root_loop: Node +) -> Set[Variable]: + root_children = subtree_of_type(pet, root_loop, CUNode) + loop_node_ids = [n.id for n in root_children] + fwVars = set() + + raw = set() + war = set() + waw = set() + sub = root_children + for sub_node in sub: + raw.update(pet.get_dep(sub_node, DepType.RAW, False)) + war.update(pet.get_dep(sub_node, DepType.WAR, False)) + waw.update(pet.get_dep(sub_node, DepType.WAW, False)) + + for var in undefinedVarsInLoop: + if var not in fwVars: + for i in raw: + if i[2].var_name == var and i[0] in loop_node_ids and i[1] in loop_node_ids: + for e in itertools.chain(war, waw): + if e[2].var_name == var and e[0] in loop_node_ids and e[1] in loop_node_ids: + if e[2].sink_line == i[2].source_line: + fwVars.add(var) + + return fwVars + + +def unused_is_first_written_in_loop(pet: PEGraphX, dep: Dependency, root_loop: Node) -> bool: + """Checks whether a variable is first written inside the current node + + :param var: + :param raw_deps: raw dependencies of the loop + :param war_deps: war dependencies of the loop + :param reverse_raw_deps: + :param reverse_war_deps: + :param tree: subtree of the loop + :return: true if first written + """ + + result = False + children = subtree_of_type(pet, root_loop, CUNode) + + for v in children: + for t, d in [ + (t, d) + for s, t, d in out_edges(pet, v.id, EdgeType.DATA) + if d.dtype == DepType.WAR or d.dtype == DepType.WAW + ]: + if d.var_name is None: + return False + assert d.var_name is not None + if dep.var_name == d.var_name: + if dep.source_line == d.sink_line: + result = True + break + # None may occur because __get_variables doesn't check for actual elements + return result diff --git a/discopop_explorer/functions/__init__.py b/discopop_explorer/functions/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/discopop_explorer/parallel_utils.py b/discopop_explorer/parallel_utils.py index a5085de01..bacfee5f3 100644 --- a/discopop_explorer/parallel_utils.py +++ b/discopop_explorer/parallel_utils.py @@ -12,6 +12,8 @@ from discopop_explorer.aliases.NodeID import NodeID from typing import Any, List, Optional, Set, Tuple +from discopop_explorer.functions.PEGraph.traversal.children import direct_children + global_pet: Optional[PEGraphX] = None @@ -24,14 +26,14 @@ def pet_function_metadata_parse_func(func_node: FunctionNode) -> Tuple[NodeID, A if global_pet is None: raise ValueError("global_pet is None!") - stack: List[Node] = global_pet.direct_children(func_node) + stack: List[Node] = direct_children(global_pet, func_node) func_node.children_cu_ids = [node.id for node in stack] local_children: Set[NodeID] = set() while stack: child = stack.pop() local_children.add(child.id) - children = global_pet.direct_children(child) + children = direct_children(global_pet, child) func_node.children_cu_ids.extend([node.id for node in children]) stack.extend(children) diff --git a/discopop_explorer/pattern_detection.py b/discopop_explorer/pattern_detection.py index d27080df8..6b09ff126 100644 --- a/discopop_explorer/pattern_detection.py +++ b/discopop_explorer/pattern_detection.py @@ -11,6 +11,8 @@ from alive_progress import alive_bar # type: ignore +from discopop_explorer.functions.PEGraph.queries.edges import out_edges +from discopop_explorer.functions.PEGraph.queries.nodes import all_nodes from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import VarName from discopop_explorer.pattern_detectors.task_parallelism.task_parallelism_detector import ( build_preprocessed_graph_and_run_detection as detect_tp, @@ -48,11 +50,11 @@ def __merge(self, loop_type: bool, remove_dummies: bool) -> None: :param remove_dummies: remove dummy nodes """ dummies_to_remove = set() - for node in self.pet.all_nodes(): + for node in all_nodes(self.pet): if not loop_type or isinstance(node, LoopNode): if remove_dummies and isinstance(node, DummyNode): continue - for s, t, e in self.pet.out_edges(node.id, [EdgeType.CHILD, EdgeType.CALLSNODE]): + for s, t, e in out_edges(self.pet, node.id, [EdgeType.CHILD, EdgeType.CALLSNODE]): if remove_dummies and isinstance(self.pet.node_at(t), DummyNode): dummies_to_remove.add(t) diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py index 6bb5ad9f5..f8f432278 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py @@ -14,6 +14,9 @@ from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.classes.patterns.PatternInfo import PatternInfo +from discopop_explorer.functions.PEGraph.properties.check_reachability import check_reachability +from discopop_explorer.functions.PEGraph.traversal.children import direct_children +from discopop_explorer.functions.PEGraph.traversal.successors import direct_successors from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, ) @@ -448,13 +451,13 @@ def find_combinations_within_function_body( continue # check reachability in both directions via successor edges # consider children, as loop nodes do not have successors on their own - for region_1_child in pet.direct_children(pet.node_at(region_1.contained_regions[0].node_id)): - for region_2_child in pet.direct_children(pet.node_at(region_2.contained_regions[0].node_id)): + for region_1_child in direct_children(pet, pet.node_at(region_1.contained_regions[0].node_id)): + for region_2_child in direct_children(pet, pet.node_at(region_2.contained_regions[0].node_id)): if region_1_child == region_2_child: continue - if pet.check_reachability(region_2_child, region_1_child, [EdgeType.SUCCESSOR]): + if check_reachability(pet, region_2_child, region_1_child, [EdgeType.SUCCESSOR]): result.append((region_1, region_2)) - elif pet.check_reachability(region_1_child, region_2_child, [EdgeType.SUCCESSOR]): + elif check_reachability(pet, region_1_child, region_2_child, [EdgeType.SUCCESSOR]): result.append((region_2, region_1)) # remove duplicates (deterministic ordering not relevant, hence list(set(..)) is fine) result = list(set(result)) @@ -472,17 +475,17 @@ def find_true_successor_combinations( for region_1, region_2 in intra_function_combinations: true_successors = True queue: List[CUNode] = cast( - List[CUNode], pet.direct_children(pet.node_at(region_1.contained_regions[0].node_id)) + List[CUNode], direct_children(pet, pet.node_at(region_1.contained_regions[0].node_id)) ) visited: List[CUNode] = [] while queue: current_node: CUNode = queue.pop() visited.append(current_node) - if current_node in pet.direct_children(pet.node_at(region_2.contained_regions[0].node_id)): + if current_node in direct_children(pet, pet.node_at(region_2.contained_regions[0].node_id)): # reached region_2 continue # region_2 not reached - successors = pet.direct_successors(current_node) + successors = direct_successors(pet, current_node) if len(successors) == 0: # end of the function body reached, region_2 not reached true_successors = False diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py index b60a663ac..00925a1cb 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py @@ -11,6 +11,7 @@ from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID +from discopop_explorer.functions.PEGraph.queries.variables import get_variable from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, ) @@ -128,9 +129,9 @@ def get_as_metadata( # get type of mapped variables var_names_types_and_sizes: List[Tuple[VarName, str, int]] = [] for var_name in self.var_names: - var_obj = pet.get_variable(self.sink_cu_id, var_name) + var_obj = get_variable(pet, self.sink_cu_id, var_name) if var_obj is None: - var_obj = pet.get_variable(self.source_cu_id, var_name) + var_obj = get_variable(pet, self.source_cu_id, var_name) if var_obj is None: var_names_types_and_sizes.append((var_name, "", 1)) else: diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py index 7ec36cc61..a3329c3a8 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py @@ -12,6 +12,7 @@ from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID +from discopop_explorer.functions.PEGraph.queries.variables import get_variable from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, ) @@ -127,9 +128,9 @@ def get_as_metadata( # get type of mapped variables var_names_types_and_sizes: List[Tuple[VarName, str, int]] = [] for var_name in self.var_names: - var_obj = pet.get_variable(self.sink_cu_id, var_name) + var_obj = get_variable(pet, self.sink_cu_id, var_name) if var_obj is None: - var_obj = pet.get_variable(self.source_cu_id, var_name) + var_obj = get_variable(pet, self.source_cu_id, var_name) if var_obj is None: var_names_types_and_sizes.append((var_name, "", 1)) else: diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py index e5191c95a..a8c1822df 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py @@ -13,6 +13,8 @@ from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.LineID import LineID from discopop_explorer.aliases.NodeID import NodeID +from discopop_explorer.functions.PEGraph.queries.variables import get_variable +from discopop_explorer.functions.PEGraph.traversal.parent import get_parent_function from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, ) @@ -176,12 +178,12 @@ def get_as_metadata_using_variable_names( # get type of mapped variables var_names_types_and_sizes: List[Tuple[VarName, str, int]] = [] for var_name in self.variable_names: - var_obj = pet.get_variable(self.sink_cu_id, var_name) + var_obj = get_variable(pet, self.sink_cu_id, var_name) source_cu_id = ( self.asynchronous_source_cu_id if self.asynchronous_possible else self.synchronous_source_cu_id ) if var_obj is None: - var_obj = pet.get_variable(cast(NodeID, source_cu_id), var_name) + var_obj = get_variable(pet, cast(NodeID, source_cu_id), var_name) if var_obj is None: var_names_types_and_sizes.append((var_name, "", 1)) else: @@ -236,12 +238,12 @@ def get_as_metadata_using_variable_names_and_memory_regions( # get type of mapped variables var_names_types_and_sizes: List[Tuple[VarName, str, int]] = [] for var_name in self.variable_names: - var_obj = pet.get_variable(self.sink_cu_id, var_name) + var_obj = get_variable(pet, self.sink_cu_id, var_name) source_cu_id = ( self.asynchronous_source_cu_id if self.asynchronous_possible else self.synchronous_source_cu_id ) if var_obj is None: - var_obj = pet.get_variable(cast(NodeID, source_cu_id), var_name) + var_obj = get_variable(pet, cast(NodeID, source_cu_id), var_name) if var_obj is None: var_names_types_and_sizes.append((var_name, "", 1)) else: @@ -279,7 +281,7 @@ def convert_memory_regions_to_variable_names( memory_regions_to_functions_and_variables: Dict[MemoryRegion, Dict[NodeID, Set[VarName]]], ) -> None: self.variable_names = set() - parent_function_id = pet.get_parent_function(pet.node_at(self.synchronous_source_cu_id)).id + parent_function_id = get_parent_function(pet, pet.node_at(self.synchronous_source_cu_id)).id for mem_reg in self.memory_regions: if parent_function_id in memory_regions_to_functions_and_variables[mem_reg]: diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py index bf70e191a..7b01f85bd 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py @@ -14,6 +14,9 @@ from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.DepType import DepType from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.queries.edges import in_edges, out_edges +from discopop_explorer.functions.PEGraph.queries.subtree import subtree_of_type +from discopop_explorer.functions.PEGraph.traversal.parent import get_parent_function from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, ) @@ -25,16 +28,16 @@ def get_written_and_read_memory_regions_by_cu( ) -> Tuple[Dict[NodeID, Set[MemoryRegion]], Dict[NodeID, Set[MemoryRegion]]]: all_function_cu_ids: Set[NodeID] = set() for region in contained_regions: - parent_function = pet.get_parent_function(pet.node_at(region.node_id)) + parent_function = get_parent_function(pet, pet.node_at(region.node_id)) - subtree = pet.subtree_of_type(parent_function, CUNode) + subtree = subtree_of_type(pet, parent_function, CUNode) all_function_cu_ids.update([NodeID(n.id) for n in subtree]) written_memory_regions_by_cu_id: Dict[NodeID, Set[MemoryRegion]] = dict() read_memory_regions_by_cu_id: Dict[NodeID, Set[MemoryRegion]] = dict() for cu_id in all_function_cu_ids: - in_dep_edges = pet.in_edges(cu_id, EdgeType.DATA) - out_dep_edges = pet.out_edges(cu_id, EdgeType.DATA) + in_dep_edges = in_edges(pet, cu_id, EdgeType.DATA) + out_dep_edges = out_edges(pet, cu_id, EdgeType.DATA) written_memory_regions = [ MemoryRegion(cast(str, d.memory_region)) @@ -80,9 +83,9 @@ def get_cu_and_varname_to_memory_regions( all_function_cu_ids: Set[NodeID] = set() for region in contained_regions: - parent_function = pet.get_parent_function(pet.node_at(region.node_id)) + parent_function = get_parent_function(pet, pet.node_at(region.node_id)) - subtree = pet.subtree_of_type(parent_function, CUNode) + subtree = subtree_of_type(pet, parent_function, CUNode) all_function_cu_ids.update([NodeID(n.id) for n in subtree]) for cu_id in all_function_cu_ids: @@ -91,7 +94,7 @@ def get_cu_and_varname_to_memory_regions( # only out_deps considered, as in_deps might use variable names # which originate from different source code scopes - out_dep_edges = pet.out_edges(cu_id, EdgeType.DATA) + out_dep_edges = out_edges(pet, cu_id, EdgeType.DATA) for _, _, dep in out_dep_edges: if dep.var_name is None or dep.memory_region is None or len(dep.memory_region) == 0: continue diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py index 5cb8eee59..bcebdb12e 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py @@ -21,6 +21,10 @@ from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.queries.edges import in_edges, out_edges +from discopop_explorer.functions.PEGraph.queries.subtree import subtree_of_type +from discopop_explorer.functions.PEGraph.traversal.children import direct_children +from discopop_explorer.functions.PEGraph.traversal.parent import get_parent_function from discopop_explorer.pattern_detectors.combined_gpu_patterns.CombinedGPURegions import CombinedGPURegion from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, @@ -50,7 +54,7 @@ def populate_live_data( + [v.name for v in gpu_loop.reduction_vars_ids] ) # set liveness within loop - subtree = pet.subtree_of_type(pet.node_at(gpu_loop.node_id), CUNode) + subtree = subtree_of_type(pet, pet.node_at(gpu_loop.node_id), CUNode) for var in live_in_loop: if var not in liveness: liveness[var] = [] @@ -162,7 +166,7 @@ def extend_data_lifespan( # split cu_ids by their parent function (used to reduce the complexity of the following step cu_ids_by_parent_functions: Dict[FunctionNode, List[NodeID]] = dict() for cu_id in live_data[mem_reg]: - parent_function = pet.get_parent_function(pet.node_at(cu_id)) + parent_function = get_parent_function(pet, pet.node_at(cu_id)) if parent_function not in cu_ids_by_parent_functions: cu_ids_by_parent_functions[parent_function] = [] cu_ids_by_parent_functions[parent_function].append(cu_id) @@ -205,12 +209,12 @@ def extend_data_lifespan( new_path_node_found = True # set mem_reg to live in every child of CU - for _, child_id, _ in pet.out_edges(cu_id, EdgeType.CHILD): + for _, child_id, _ in out_edges(pet, cu_id, EdgeType.CHILD): if child_id not in live_data[mem_reg]: function_new_entries.append((mem_reg, child_id)) # set mem_reg to live in every called function of CU - for _, called_node, _ in pet.out_edges(cu_id, EdgeType.CALLSNODE): + for _, called_node, _ in out_edges(pet, cu_id, EdgeType.CALLSNODE): if called_node not in live_data[mem_reg]: function_new_entries.append((mem_reg, called_node)) @@ -227,9 +231,9 @@ def extend_data_lifespan( # if path_node is located within a loop, add the other loop cus to the path as well to_be_added: List[CUNode] = [] for path_node in path_nodes: - parent_node = [pet.node_at(s) for s, t, d in pet.in_edges(path_node.id, EdgeType.CHILD)][0] + parent_node = [pet.node_at(s) for s, t, d in in_edges(pet, path_node.id, EdgeType.CHILD)][0] if parent_node.type == NodeType.LOOP: - for _, loop_cu_id, _ in pet.out_edges(parent_node.id, EdgeType.CHILD): + for _, loop_cu_id, _ in out_edges(pet, parent_node.id, EdgeType.CHILD): loop_cu = cast(CUNode, pet.node_at(loop_cu_id)) if loop_cu not in path_nodes and loop_cu not in to_be_added: to_be_added.append(loop_cu) @@ -242,8 +246,8 @@ def extend_data_lifespan( # calculate subtree without including called functions subtree_without_called_functions = [ cu - for cu in pet.direct_children(path_node) - if cu not in [pet.node_at(t) for s, t, d in pet.out_edges(path_node.id, EdgeType.CALLSNODE)] + for cu in direct_children(pet, path_node) + if cu not in [pet.node_at(t) for s, t, d in out_edges(pet, path_node.id, EdgeType.CALLSNODE)] ] # add path_node itself to the subtree subtree_without_called_functions.append(path_node) @@ -283,7 +287,7 @@ def calculate_host_liveness( all_function_cu_ids: Set[NodeID] = set() for region in comb_gpu_reg.contained_regions: - parent_function = pet.get_parent_function(pet.node_at(region.node_id)) + parent_function = get_parent_function(pet, pet.node_at(region.node_id)) all_function_cu_ids.update(get_function_body_cus_without_called_functions(pet, parent_function)) all_function_host_cu_ids = [cu_id for cu_id in all_function_cu_ids if cu_id not in comb_gpu_reg.device_cu_ids] @@ -292,10 +296,10 @@ def calculate_host_liveness( shared_variables: Set[VarName] = set() shared_memory_regions: Set[MemoryRegion] = set() # get all data which is accessed by the cu_id and it's children and any device cu - subtree = pet.subtree_of_type(pet.node_at(cu_id), CUNode) + subtree = subtree_of_type(pet, pet.node_at(cu_id), CUNode) for subtree_node_id in [n.id for n in subtree]: - out_data_edges = pet.out_edges(subtree_node_id, EdgeType.DATA) - in_data_edges = pet.in_edges(subtree_node_id, EdgeType.DATA) + out_data_edges = out_edges(pet, subtree_node_id, EdgeType.DATA) + in_data_edges = in_edges(pet, subtree_node_id, EdgeType.DATA) for _, target, dep in out_data_edges: if target in comb_gpu_reg.device_cu_ids: if dep.var_name is not None: diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py index c46581d72..6acbf6846 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py @@ -13,6 +13,8 @@ from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.queries.edges import in_edges, out_edges +from discopop_explorer.functions.PEGraph.traversal.parent import get_parent_function from discopop_explorer.pattern_detectors.combined_gpu_patterns.CombinedGPURegions import CombinedGPURegion global_write_unique_id = 0 @@ -52,7 +54,7 @@ def propagate_writes( Stop on the level of the base function""" parent_functions: List[NodeID] = [] for region in comb_gpu_reg.contained_regions: - parent_functions.append(pet.get_parent_function(pet.node_at(region.node_id)).id) + parent_functions.append(get_parent_function(pet, pet.node_at(region.node_id)).id) modification_found = True while modification_found: @@ -66,7 +68,7 @@ def propagate_writes( # no write continue # propagate to parents - for parent_id, _, _ in pet.in_edges(cu_id_1, EdgeType.CHILD): + for parent_id, _, _ in in_edges(pet, cu_id_1, EdgeType.CHILD): if parent_id in parent_functions: # do not propagate above the function which contains the GPU Regions continue @@ -90,20 +92,20 @@ def propagate_writes( # no write continue # propagate to successors - for _, successor_id, _ in pet.out_edges(cu_id_1, EdgeType.SUCCESSOR): + for _, successor_id, _ in out_edges(pet, cu_id_1, EdgeType.SUCCESSOR): if (successor_id, write_identifier_1) not in writes[mem_reg]: writes[mem_reg].add((successor_id, write_identifier_1)) modification_found = True # propagated to successor # propagate to children of successors - for _, child_id, _ in pet.out_edges(successor_id, EdgeType.CHILD): + for _, child_id, _ in out_edges(pet, successor_id, EdgeType.CHILD): if (child_id, write_identifier_1) not in writes[mem_reg]: writes[mem_reg].add((child_id, write_identifier_1)) modification_found = True # propagated to children of successor # propagate to called functions of successors - for _, called_node_id, _ in pet.out_edges(successor_id, EdgeType.CALLSNODE): + for _, called_node_id, _ in out_edges(pet, successor_id, EdgeType.CALLSNODE): if (called_node_id, write_identifier_1) not in writes[mem_reg]: writes[mem_reg].add((called_node_id, write_identifier_1)) modification_found = True @@ -125,8 +127,8 @@ def propagate_writes( continue if pet_node.return_instructions_count > 0: # propagate write to calling cus - parent_function = pet.get_parent_function(pet_node) - callees = [s for s, t, d in pet.in_edges(parent_function.id, EdgeType.CALLSNODE)] + parent_function = get_parent_function(pet, pet_node) + callees = [s for s, t, d in in_edges(pet, parent_function.id, EdgeType.CALLSNODE)] for callee_id in callees: if (callee_id, write_identifier) not in writes[mem_reg]: writes[mem_reg].add((callee_id, write_identifier)) diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py index 9e08dfc4a..dd8811aaf 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py @@ -23,6 +23,11 @@ from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.properties.is_predecessor import is_predecessor +from discopop_explorer.functions.PEGraph.queries.edges import in_edges, out_edges +from discopop_explorer.functions.PEGraph.queries.nodes import all_nodes +from discopop_explorer.functions.PEGraph.traversal.parent import get_parent_function +from discopop_explorer.functions.PEGraph.traversal.successors import direct_successors from discopop_explorer.pattern_detectors.combined_gpu_patterns.CombinedGPURegions import CombinedGPURegion from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Enums import UpdateType from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Update import Update @@ -125,7 +130,7 @@ def find_required_updates(self, pet: PEGraphX, new_device_id: int) -> Set[Tuple[ for ident, origin in missing_write_identifiers: if last_write_location is None: last_write_location = origin - if pet.is_predecessor(cast(NodeID, last_write_location), cast(NodeID, origin)): + if is_predecessor(pet, cast(NodeID, last_write_location), cast(NodeID, origin)): last_write_location = origin required_updates.add((mem_reg, device_id_1, device_id_2, cast(NodeID, last_write_location))) @@ -170,7 +175,7 @@ def request_updates_from_other_devices( for ident, origin in missing_identifiers: if last_write_location is None: last_write_location = origin - if pet.is_predecessor(cast(NodeID, last_write_location), cast(NodeID, origin)): + if is_predecessor(pet, cast(NodeID, last_write_location), cast(NodeID, origin)): last_write_location = origin required_updates.add((mem_reg, other_device_id, new_device_id, cast(NodeID, last_write_location))) @@ -306,7 +311,7 @@ def check_validity_of_potential_merge_node(node_id: NodeID) -> bool: return False if ( "return" in str(potential_merge_node.basic_block_id) - and potential_merge_node.end_position() == pet.get_parent_function(potential_merge_node).end_position() + and potential_merge_node.end_position() == get_parent_function(pet, potential_merge_node).end_position() ): # do not consider return BB as merge node return False @@ -315,7 +320,7 @@ def check_validity_of_potential_merge_node(node_id: NodeID) -> bool: if len(successors) == 0: raise ValueError("Empty list of successors!") - parent_function = pet.get_parent_function(pet.node_at(successors[0])) + parent_function = get_parent_function(pet, pet.node_at(successors[0])) post_dominators = parent_function.get_immediate_post_dominators(pet) # initialize lists of current post dominators @@ -378,14 +383,14 @@ def identify_updates( # get parent functions parent_functions: Set[NodeID] = set() for region in comb_gpu_reg.contained_regions: - parent_functions.add(pet.get_parent_function(pet.node_at(region.node_id)).id) + parent_functions.add(get_parent_function(pet, pet.node_at(region.node_id)).id) for parent_function_id in parent_functions: print("IDENTIFY UPDATES FOR: ", pet.node_at(parent_function_id).name, file=sys.stderr) # determine entry points entry_points: List[NodeID] = [] - for function_child_id in [t for s, t, d in pet.out_edges(parent_function_id, EdgeType.CHILD)]: - in_successor_edges = pet.in_edges(function_child_id, EdgeType.SUCCESSOR) + for function_child_id in [t for s, t, d in out_edges(pet, parent_function_id, EdgeType.CHILD)]: + in_successor_edges = in_edges(pet, function_child_id, EdgeType.SUCCESSOR) if len(in_successor_edges) == 0 and pet.node_at(function_child_id).type == NodeType.CU: entry_points.append(function_child_id) @@ -458,7 +463,7 @@ def __calculate_updates( identified_updates.update(required_updates) # calculate successors of current node - # successors = [cast(NodeID, t) for s, t, d in pet.out_edges(cur_node_id, EdgeType.SUCCESSOR)] + # successors = [cast(NodeID, t) for s, t, d in out_edges(pet, cur_node_id, EdgeType.SUCCESSOR)] successors = [t for s, t, d in unrolled_function_graph.out_edges(cur_node_id, data="data")] if len(successors) == 0: @@ -528,7 +533,7 @@ def create_circle_free_function_graphs(pet: PEGraphX, add_dummy_node: bool = Tru unrolled_function_graphs: Dict[FunctionNode, nx.MultiDiGraph] = dict() # initialize the function graphs - for function in pet.all_nodes(type=FunctionNode): + for function in all_nodes(pet, type=FunctionNode): # get subgraph for function function_subgraph = pet.g.subgraph(function.children_cu_ids).copy() # remove all but successor edges @@ -572,7 +577,7 @@ def create_circle_free_function_graphs(pet: PEGraphX, add_dummy_node: bool = Tru # ==> Identify cycle entries entry_nodes: Set[NodeID] = set() for node_id, _, _ in cycle_edges: - predecessors = [s for s, t, d in pet.in_edges(node_id, EdgeType.SUCCESSOR)] + predecessors = [s for s, t, d in in_edges(pet, node_id, EdgeType.SUCCESSOR)] if len(predecessors) == 0: entry_nodes.add(node_id) continue @@ -585,28 +590,28 @@ def create_circle_free_function_graphs(pet: PEGraphX, add_dummy_node: bool = Tru print("cyc: ", cycle_nodes) print("exit: ", potential_exit_node) potential_cycle_successor_nodes = [ - t for s, t, d in pet.out_edges(potential_exit_node, EdgeType.SUCCESSOR) if t not in cycle_nodes + t for s, t, d in out_edges(pet, potential_exit_node, EdgeType.SUCCESSOR) if t not in cycle_nodes ] print("POT: ", potential_cycle_successor_nodes) # only consider such cycle_successors which DO NOT share a direct parent with the potential_exit_node, except for functions pen_parents = [ s - for s, t, d in pet.in_edges(potential_exit_node, EdgeType.CHILD) + for s, t, d in in_edges(pet, potential_exit_node, EdgeType.CHILD) if type(pet.node_at(s)) != FunctionNode ] filtered_pcsn = [] for pcsn in potential_cycle_successor_nodes: pcsn_parents = [ - s for s, t, d in pet.in_edges(pcsn, EdgeType.CHILD) if type(pet.node_at(s)) != FunctionNode + s for s, t, d in in_edges(pet, pcsn, EdgeType.CHILD) if type(pet.node_at(s)) != FunctionNode ] if len([nid for nid in pen_parents if nid in pcsn_parents]) == 0: # no shared parents filtered_pcsn.append(pcsn) # second chance: add pcsn, if it has a successor outside the given parent - for successor in pet.direct_successors(pet.node_at(pcsn)): + for successor in direct_successors(pet, pet.node_at(pcsn)): valid = True - for parent in [s for s, t, d in pet.in_edges(successor.id)]: + for parent in [s for s, t, d in in_edges(pet, successor.id)]: if parent in pcsn_parents: valid = False break @@ -694,7 +699,7 @@ def add_accesses_from_called_functions( while values_propagated: cycles += 1 values_propagated = False - for function in pet.all_nodes(type=FunctionNode): + for function in all_nodes(pet, type=FunctionNode): print("FUNCTION: ", function.name) memory_accesses = function.get_memory_accesses(writes_by_device) if force_called_functions_to_host: @@ -709,7 +714,7 @@ def add_accesses_from_called_functions( del memory_accesses[key] # add memory_accesses to calling CU's in writes_by_device - called_by = [s for s, t, d in pet.in_edges(function.id, EdgeType.CALLSNODE)] + called_by = [s for s, t, d in in_edges(pet, function.id, EdgeType.CALLSNODE)] print("\tcalled by: ", called_by) for device_id in memory_accesses: if device_id not in writes_by_device: @@ -740,14 +745,14 @@ def identify_updates_in_unrolled_function_graphs( # get parent functions parent_functions: Set[NodeID] = set() for region in comb_gpu_reg.contained_regions: - parent_functions.add(pet.get_parent_function(pet.node_at(region.node_id)).id) + parent_functions.add(get_parent_function(pet, pet.node_at(region.node_id)).id) for parent_function_id in parent_functions: print("IDENTIFY UPDATES FOR: ", pet.node_at(parent_function_id).name, file=sys.stderr) # determine entry points entry_points: List[NodeID] = [] - for function_child_id in [t for s, t, d in pet.out_edges(parent_function_id, EdgeType.CHILD)]: - in_successor_edges = pet.in_edges(function_child_id, EdgeType.SUCCESSOR) + for function_child_id in [t for s, t, d in out_edges(pet, parent_function_id, EdgeType.CHILD)]: + in_successor_edges = in_edges(pet, function_child_id, EdgeType.SUCCESSOR) if len(in_successor_edges) == 0 and pet.node_at(function_child_id).type == NodeType.CU: entry_points.append(function_child_id) diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_5.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_5.py index ea1d5d15b..bfe29785a 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_5.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_5.py @@ -11,6 +11,7 @@ from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID +from discopop_explorer.functions.PEGraph.traversal.parent import get_parent_function from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, ) @@ -28,7 +29,7 @@ def propagate_variable_name_associations( var_names = memory_regions_to_cus_and_variables[mem_reg][cu_id] cu_node = pet.node_at(cu_id) # get parent function - parent = pet.get_parent_function(cu_node) + parent = get_parent_function(pet, cu_node) # save variable name association for parent function if mem_reg not in updated_dict: diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py index e6d751d62..cd6530b72 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py @@ -20,6 +20,12 @@ from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.DepType import DepType from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.properties.is_predecessor import is_predecessor +from discopop_explorer.functions.PEGraph.queries.edges import in_edges +from discopop_explorer.functions.PEGraph.queries.nodes import all_nodes +from discopop_explorer.functions.PEGraph.queries.paths import get_path_nodes_between +from discopop_explorer.functions.PEGraph.traversal.parent import get_parent_function +from discopop_explorer.functions.PEGraph.traversal.successors import direct_successors from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, ) @@ -146,8 +152,8 @@ def add_aliases( memory_regions_to_functions_and_variables: Dict[MemoryRegion, Dict[NodeID, Set[VarName]]], ) -> Set[Update]: for update in issued_updates: - source_parent_function_node = pet.get_parent_function(pet.node_at(update.synchronous_source_cu_id)) - sink_parent_function_node = pet.get_parent_function(pet.node_at(update.sink_cu_id)) + source_parent_function_node = get_parent_function(pet, pet.node_at(update.synchronous_source_cu_id)) + sink_parent_function_node = get_parent_function(pet, pet.node_at(update.sink_cu_id)) if source_parent_function_node == sink_parent_function_node: # add alias information from function level modification_found = True @@ -218,7 +224,7 @@ def identify_end_of_life_points( for mem_reg in memory_region_liveness_by_device[device_id]: # check if mem_reg is live in all successors of all contained cu's for cu_id in memory_region_liveness_by_device[device_id][mem_reg]: - for successor_node in pet.direct_successors(pet.node_at(cu_id)): + for successor_node in direct_successors(pet, pet.node_at(cu_id)): if successor_node.id not in memory_region_liveness_by_device[device_id][mem_reg]: # mem_reg is not live anymore. create an EOL point if mem_reg in mem_reg_aliases: @@ -240,11 +246,11 @@ def identify_end_of_life_points( # in both cases, eol is covered by the exit_point and can be ignored if ( ( - pet.is_predecessor(exit_point.source_cu_id, eol[0]) - and pet.is_predecessor(exit_point.sink_cu_id, eol[1]) + is_predecessor(pet, exit_point.source_cu_id, eol[0]) + and is_predecessor(pet, exit_point.sink_cu_id, eol[1]) ) - or pet.is_predecessor(eol[0], exit_point.source_cu_id) - and pet.is_predecessor(eol[1], exit_point.sink_cu_id) + or is_predecessor(pet, eol[0], exit_point.source_cu_id) + and is_predecessor(pet, eol[1], exit_point.sink_cu_id) ): # check if memory regions overlap, i.e. if the exit_point covers eol if len([mem_reg for mem_reg in exit_point.memory_regions if mem_reg in eol[2]]) > 0: @@ -257,7 +263,7 @@ def identify_end_of_life_points( eol_exit_points: Set[ExitPoint] = set() for eol in eol_points: - parent_function_node_id = pet.get_parent_function(pet.node_at(eol[0])).id + parent_function_node_id = get_parent_function(pet, pet.node_at(eol[0])).id var_names: Set[VarName] = set() for mem_reg in eol[2]: if parent_function_node_id in memory_regions_to_functions_and_variables[mem_reg]: @@ -265,7 +271,8 @@ def identify_end_of_life_points( memory_regions = set(eol[2]) # check if the exited data is required by another function # if so, mark the exit point as ExitPointType.FROM - path_nodes = pet.get_path_nodes_between( + path_nodes = get_path_nodes_between( + pet, cast(CUNode, pet.node_at(eol[1])), cast(CUNode, pet.node_at(eol[0])), [EdgeType.SUCCESSOR, EdgeType.CHILD], @@ -275,10 +282,10 @@ def identify_end_of_life_points( for path_node in path_nodes: in_raw_edges_from_outside += [ (s, t, d) - for s, t, d in pet.in_edges(path_node.id, EdgeType.DATA) + for s, t, d in in_edges(pet, path_node.id, EdgeType.DATA) if d.dtype == DepType.RAW and d.memory_region in memory_regions - and pet.get_parent_function(pet.node_at(s)) != pet.get_parent_function(pet.node_at(t)) + and get_parent_function(pet, pet.node_at(s)) != get_parent_function(pet, pet.node_at(t)) ] if len(in_raw_edges_from_outside) > 0: # value is read -> Copy back to the host so the value does not get discarded @@ -300,7 +307,7 @@ def extend_region_liveness_using_unrolled_functions( ) -> Dict[MemoryRegion, List[NodeID]]: # TODO: potential optimization: invert the 'liveness' dict to allow faster membership check - for function in pet.all_nodes(FunctionNode): + for function in all_nodes(pet, FunctionNode): print("FUNCTION: ", function.name) unrolled_function_graph = unrolled_function_graphs[function] queue: List[Tuple[NodeID, MemoryRegion, List[NodeID]]] = [] diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py index 0c4b416ec..8d83bdad1 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py @@ -15,6 +15,7 @@ from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.queries.edges import out_edges def get_contained_lines(start_line: str, end_line: str) -> List[str]: @@ -28,7 +29,7 @@ def get_contained_lines(start_line: str, end_line: str) -> List[str]: def get_function_body_cus_without_called_functions(pet: PEGraphX, function_node: FunctionNode) -> List[NodeID]: - queue = [t for s, t, d in pet.out_edges(function_node.id, EdgeType.CHILD)] + queue = [t for s, t, d in out_edges(pet, function_node.id, EdgeType.CHILD)] visited: Set[NodeID] = set() while queue: current = queue.pop(0) @@ -36,8 +37,8 @@ def get_function_body_cus_without_called_functions(pet: PEGraphX, function_node: current_node = pet.node_at(current) # add children if they do not result from a call - children = [t for s, t, d in pet.out_edges(current, EdgeType.CHILD)] - called = [t for s, t, d in pet.out_edges(current, EdgeType.CALLSNODE)] + children = [t for s, t, d in out_edges(pet, current, EdgeType.CHILD)] + called = [t for s, t, d in out_edges(pet, current, EdgeType.CALLSNODE)] queue += [c for c in children if c not in visited and c not in called] # todo add check for call return list(visited) diff --git a/discopop_explorer/pattern_detectors/do_all_detector.py b/discopop_explorer/pattern_detectors/do_all_detector.py index 13579d1f3..a7c2181ea 100644 --- a/discopop_explorer/pattern_detectors/do_all_detector.py +++ b/discopop_explorer/pattern_detectors/do_all_detector.py @@ -10,6 +10,14 @@ from typing import List, Dict, Optional, Set, Tuple, cast import warnings +from discopop_explorer.functions.PEGraph.properties.depends_ignore_readonly import depends_ignore_readonly +from discopop_explorer.functions.PEGraph.properties.is_loop_index import is_loop_index +from discopop_explorer.functions.PEGraph.properties.is_readonly_inside_loop_body import is_readonly_inside_loop_body +from discopop_explorer.functions.PEGraph.queries.edges import in_edges, out_edges +from discopop_explorer.functions.PEGraph.queries.nodes import all_nodes +from discopop_explorer.functions.PEGraph.queries.subtree import subtree_of_type +from discopop_explorer.functions.PEGraph.queries.variables import get_variables +from discopop_explorer.functions.PEGraph.traversal.parent import get_parent_function from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore @@ -87,7 +95,7 @@ def run_detection( global global_pet global_pet = pet result: List[DoAllInfo] = [] - nodes = pet.all_nodes(LoopNode) + nodes = all_nodes(pet, LoopNode) warnings.warn("DOALL DETECTION CURRENTLY ASSUMES THE EXISTENCE OF DEPENDENCY METADATA!") @@ -146,11 +154,11 @@ def __detect_do_all(pet: PEGraphX, root_loop: LoopNode) -> bool: :param root: root node :return: true if do-all """ - subnodes = [pet.node_at(t) for s, t, d in pet.out_edges(root_loop.id, [EdgeType.CHILD, EdgeType.CALLSNODE])] + subnodes = [pet.node_at(t) for s, t, d in out_edges(pet, root_loop.id, [EdgeType.CHILD, EdgeType.CALLSNODE])] # get required metadata loop_start_lines: List[LineID] = [] - root_children = pet.subtree_of_type(root_loop, (CUNode, LoopNode)) + root_children = subtree_of_type(pet, root_loop, (CUNode, LoopNode)) root_children_cus = [cast(CUNode, cu) for cu in root_children if cu.type == NodeType.CU] root_children_loops = [cast(LoopNode, cu) for cu in root_children if cu.type == NodeType.LOOP] for v in root_children_loops: @@ -159,12 +167,12 @@ def __detect_do_all(pet: PEGraphX, root_loop: LoopNode) -> bool: # get parents of root_loop parent_loops = __get_parent_loops(pet, root_loop) - parent_function_lineid = pet.get_parent_function(root_loop).start_position() + parent_function_lineid = get_parent_function(pet, root_loop).start_position() called_functions_lineids = __get_called_functions(pet, root_loop) # get variables which are defined inside the loop defined_inside_loop: List[Tuple[Variable, Set[MemoryRegion]]] = [] - tmp_loop_variables = pet.get_variables(root_children_cus) + tmp_loop_variables = get_variables(pet, root_children_cus) for var in tmp_loop_variables: if ":" in var.defLine: file_id = int(var.defLine.split(":")[0]) @@ -175,7 +183,7 @@ def __detect_do_all(pet: PEGraphX, root_loop: LoopNode) -> bool: # check if all subnodes are parallelizable file_io_warnings = [] - for node in pet.subtree_of_type(root_loop, CUNode): + for node in subtree_of_type(pet, root_loop, CUNode): if node.performs_file_io: # node is not reliably parallelizable as some kind of file-io is performed. file_io_warnings.append(node) @@ -230,17 +238,21 @@ def __check_loop_dependencies( """Returns True, if dependencies between the respective subgraphs chave been found. Returns False otherwise, which results in the potential suggestion of a Do-All pattern.""" # get recursive children of source and target - node_1_children_ids = [node.id for node in pet.subtree_of_type(node_1, CUNode)] - node_2_children_ids = [node.id for node in pet.subtree_of_type(node_2, CUNode)] + node_1_children_ids = [node.id for node in subtree_of_type(pet, node_1, CUNode)] + node_2_children_ids = [node.id for node in subtree_of_type(pet, node_2, CUNode)] # get dependency edges between children nodes deps = set() for n in node_1_children_ids + node_2_children_ids: deps.update( - [(s, t, d) for s, t, d in pet.in_edges(n, EdgeType.DATA) if s in node_1_children_ids + node_2_children_ids] + [(s, t, d) for s, t, d in in_edges(pet, n, EdgeType.DATA) if s in node_1_children_ids + node_2_children_ids] ) deps.update( - [(s, t, d) for s, t, d in pet.out_edges(n, EdgeType.DATA) if t in node_1_children_ids + node_2_children_ids] + [ + (s, t, d) + for s, t, d in out_edges(pet, n, EdgeType.DATA) + if t in node_1_children_ids + node_2_children_ids + ] ) # get memory regions which are defined inside the loop @@ -256,7 +268,8 @@ def __check_loop_dependencies( max_considered_intra_iteration_dep_level = max(dep_source_nesting_level, dep_target_nesting_level) # check if targeted variable is readonly inside loop - if pet.is_readonly_inside_loop_body( + if is_readonly_inside_loop_body( + pet, dep, root_loop, root_children_cus, @@ -267,7 +280,7 @@ def __check_loop_dependencies( continue # check if targeted variable is loop index - if pet.is_loop_index(dep.var_name, loop_start_lines, root_children_cus): + if is_loop_index(pet, dep.var_name, loop_start_lines, root_children_cus): continue # ignore dependencies where either source or sink do not lie within root_loop @@ -363,10 +376,10 @@ def __old_detect_do_all(pet: PEGraphX, root_loop: CUNode) -> bool: :param root: root node :return: true if do-all """ - subnodes = [pet.node_at(t) for s, t, d in pet.out_edges(root_loop.id, [EdgeType.CHILD, EdgeType.CALLSNODE])] + subnodes = [pet.node_at(t) for s, t, d in out_edges(pet, root_loop.id, [EdgeType.CHILD, EdgeType.CALLSNODE])] # check if all subnodes are parallelizable - for node in pet.subtree_of_type(root_loop, CUNode): + for node in subtree_of_type(pet, root_loop, CUNode): if node.performs_file_io: # node is not reliably parallelizable as some kind of file-io is performed. return False @@ -375,7 +388,7 @@ def __old_detect_do_all(pet: PEGraphX, root_loop: CUNode) -> bool: children_cache: Dict[CUNode, List[CUNode]] = dict() dependency_cache: Dict[Tuple[CUNode, CUNode], Set[CUNode]] = dict() for j in range(i, len(subnodes)): - if pet.depends_ignore_readonly(subnodes[i], subnodes[j], root_loop): + if depends_ignore_readonly(pet, subnodes[i], subnodes[j], root_loop): return False return True @@ -392,7 +405,7 @@ def __calculate_nesting_level(pet: PEGraphX, root_loop: LoopNode, cu_node_id: st # found return nesting_level # add new parents to the queue - for in_child_edge in pet.in_edges(cast(NodeID, current_node_id), EdgeType.CHILD): + for in_child_edge in in_edges(pet, cast(NodeID, current_node_id), EdgeType.CHILD): potential_parents.append((in_child_edge[0], nesting_level + 1)) @@ -408,11 +421,11 @@ def __get_parent_loops(pet: PEGraphX, root_loop: LoopNode) -> List[LineID]: parents.append(current) # process incoming child edges - for s, t, e in pet.in_edges(current, EdgeType.CHILD): + for s, t, e in in_edges(pet, current, EdgeType.CHILD): if s not in visited and s not in queue: queue.append(s) # process incoming call edges - for s, t, e in pet.in_edges(current, EdgeType.CALLSNODE): + for s, t, e in in_edges(pet, current, EdgeType.CALLSNODE): if s not in visited and s not in queue: queue.append(s) @@ -429,10 +442,10 @@ def __get_called_functions(pet: PEGraphX, root_loop: LoopNode) -> List[LineID]: current = queue.pop() visited.add(current) # get called functions - for s, t, e in pet.out_edges(current, EdgeType.CALLSNODE): + for s, t, e in out_edges(pet, current, EdgeType.CALLSNODE): called_functions.add(t) # add children to queue - for s, t, e in pet.out_edges(current, EdgeType.CHILD): + for s, t, e in out_edges(pet, current, EdgeType.CHILD): if t not in queue and t not in visited: queue.append(t) @@ -448,13 +461,13 @@ def __check_for_problematic_function_argument_access( # if so, return True. Else. return false # find accessed function argument for source - source_pf = pet.get_parent_function(pet.node_at(source)) + source_pf = get_parent_function(pet, pet.node_at(source)) source_accessed_pf_args = [a for a in source_pf.args if a.name == dep.var_name] if len(source_accessed_pf_args) == 0: return False # find accessed function argument for target - target_pf = pet.get_parent_function(pet.node_at(target)) + target_pf = get_parent_function(pet, pet.node_at(target)) target_accessed_pf_args = [a for a in target_pf.args if a.name == dep.var_name] if len(target_accessed_pf_args) == 0: return False diff --git a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py index a38ba81a4..996d26765 100644 --- a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py +++ b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py @@ -10,6 +10,10 @@ import math from typing import Dict, List, Tuple, Optional, cast +from discopop_explorer.functions.PEGraph.queries.edges import in_edges +from discopop_explorer.functions.PEGraph.queries.nodes import all_nodes +from discopop_explorer.functions.PEGraph.queries.subtree import subtree_of_type +from discopop_explorer.functions.PEGraph.traversal.children import direct_children_or_called_nodes_of_type from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import VarName from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore @@ -102,7 +106,7 @@ def run_detection( result: List[GDInfo] = [] global __loop_iterations __loop_iterations = {} - nodes = pet.all_nodes(FunctionNode) + nodes = all_nodes(pet, FunctionNode) nodes = cast(List[FunctionNode], filter_for_hotspots(pet, cast(List[Node], nodes), hotspots)) @@ -150,10 +154,10 @@ def __test_chunk_limit(pet: PEGraphX, node: Node) -> Tuple[bool, Optional[int]]: min_iterations_count = None inner_loop_iter = {} - children = pet.direct_children_or_called_nodes_of_type(node, LoopNode) + children = direct_children_or_called_nodes_of_type(pet, node, LoopNode) - for func_child in pet.direct_children_or_called_nodes_of_type(node, FunctionNode): - children.extend(pet.direct_children_or_called_nodes_of_type(func_child, LoopNode)) + for func_child in direct_children_or_called_nodes_of_type(pet, node, FunctionNode): + children.extend(direct_children_or_called_nodes_of_type(pet, func_child, LoopNode)) for child in children: inner_loop_iter[child.start_position()] = __iterations_count(pet, child) @@ -195,7 +199,7 @@ def __get_parent_iterations(pet: PEGraphX, node: Node) -> int: :param node: current node :return: number of iterations """ - parent = pet.in_edges(node.id, [EdgeType.CHILD, EdgeType.CALLSNODE]) + parent = in_edges(pet, node.id, [EdgeType.CHILD, EdgeType.CALLSNODE]) max_iter = 1 visited = [] # used to prevent looping @@ -208,7 +212,7 @@ def __get_parent_iterations(pet: PEGraphX, node: Node) -> int: max_iter = max(1, node.loop_iterations) break visited.append(node) - parent = pet.in_edges(node.id, [EdgeType.CHILD, EdgeType.CALLSNODE]) + parent = in_edges(pet, node.id, [EdgeType.CHILD, EdgeType.CALLSNODE]) return max_iter @@ -220,12 +224,12 @@ def __detect_geometric_decomposition(pet: PEGraphX, root: Node) -> bool: :param root: root node :return: true if GD pattern was discovered """ - for loop_child in pet.subtree_of_type(root, LoopNode): + for loop_child in subtree_of_type(pet, root, LoopNode): if not (loop_child.reduction or loop_child.do_all): return False - for child in pet.direct_children_or_called_nodes_of_type(root, FunctionNode): - for child2 in pet.direct_children_or_called_nodes_of_type(child, LoopNode): + for child in direct_children_or_called_nodes_of_type(pet, root, FunctionNode): + for child2 in direct_children_or_called_nodes_of_type(pet, child, LoopNode): if not (child2.reduction or child2.do_all): return False diff --git a/discopop_explorer/pattern_detectors/pipeline_detector.py b/discopop_explorer/pattern_detectors/pipeline_detector.py index 56c30fd7b..b1d52d2da 100644 --- a/discopop_explorer/pattern_detectors/pipeline_detector.py +++ b/discopop_explorer/pattern_detectors/pipeline_detector.py @@ -9,6 +9,10 @@ from typing import List, Optional, Tuple, Dict, cast +from discopop_explorer.functions.PEGraph.properties.depends_ignore_readonly import depends_ignore_readonly +from discopop_explorer.functions.PEGraph.queries.edges import in_edges, out_edges +from discopop_explorer.functions.PEGraph.queries.nodes import all_nodes +from discopop_explorer.functions.PEGraph.queries.subtree import subtree_of_type from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore @@ -81,11 +85,11 @@ def __init__(self, pet: PEGraphX, node: Node): self._pet = pet self.coefficient = round(node.pipeline, 3) - children_start_lines = [v.start_position() for v in pet.subtree_of_type(node, LoopNode)] + children_start_lines = [v.start_position() for v in subtree_of_type(pet, node, LoopNode)] self._stages = [ pet.node_at(t) - for s, t, d in pet.out_edges(node.id, [EdgeType.CHILD, EdgeType.CALLSNODE]) + for s, t, d in out_edges(pet, node.id, [EdgeType.CHILD, EdgeType.CALLSNODE]) if is_pipeline_subnode(node, pet.node_at(t), children_start_lines) ] @@ -93,23 +97,23 @@ def __init__(self, pet: PEGraphX, node: Node): def __in_dep(self, node: Node) -> List[Tuple[NodeID, NodeID, Dependency]]: raw: List[Tuple[NodeID, NodeID, Dependency]] = [] - for n in self._pet.subtree_of_type(node, CUNode): - raw.extend((s, t, d) for s, t, d in self._pet.out_edges(n.id, EdgeType.DATA) if d.dtype == DepType.RAW) + for n in subtree_of_type(self._pet, node, CUNode): + raw.extend((s, t, d) for s, t, d in out_edges(self._pet, n.id, EdgeType.DATA) if d.dtype == DepType.RAW) nodes_before = [node] for i in range(self._stages.index(node)): - nodes_before.extend(self._pet.subtree_of_type(self._stages[i], CUNode)) + nodes_before.extend(subtree_of_type(self._pet, self._stages[i], CUNode)) return [dep for dep in raw if dep[1] in [n.id for n in nodes_before]] def __out_dep(self, node: Node) -> List[Tuple[NodeID, NodeID, Dependency]]: raw: List[Tuple[NodeID, NodeID, Dependency]] = [] - for n in self._pet.subtree_of_type(node, CUNode): - raw.extend((s, t, d) for s, t, d in self._pet.in_edges(n.id, EdgeType.DATA) if d.dtype == DepType.RAW) + for n in subtree_of_type(self._pet, node, CUNode): + raw.extend((s, t, d) for s, t, d in in_edges(self._pet, n.id, EdgeType.DATA) if d.dtype == DepType.RAW) nodes_after = [node] for i in range(self._stages.index(node) + 1, len(self._stages)): - nodes_after.extend(self._pet.subtree_of_type(self._stages[i], CUNode)) + nodes_after.extend(subtree_of_type(self._pet, self._stages[i], CUNode)) return [dep for dep in raw if dep[0] in [n.id for n in nodes_after]] @@ -171,7 +175,7 @@ def run_detection( global_pet = pet result: List[PipelineInfo] = [] - nodes = pet.all_nodes(LoopNode) + nodes = all_nodes(pet, LoopNode) nodes = cast(List[LoopNode], filter_for_hotspots(pet, cast(List[Node], nodes), hotspots)) @@ -217,11 +221,11 @@ def __detect_pipeline(pet: PEGraphX, root: Node) -> float: :return: Pipeline scalar value """ - children_start_lines = [v.start_position() for v in pet.subtree_of_type(root, LoopNode)] + children_start_lines = [v.start_position() for v in subtree_of_type(pet, root, LoopNode)] loop_subnodes = [ pet.node_at(t) - for s, t, d in pet.out_edges(root.id, [EdgeType.CHILD, EdgeType.CALLSNODE]) + for s, t, d in out_edges(pet, root.id, [EdgeType.CHILD, EdgeType.CALLSNODE]) if is_pipeline_subnode(root, pet.node_at(t), children_start_lines) ] @@ -231,7 +235,7 @@ def __detect_pipeline(pet: PEGraphX, root: Node) -> float: graph_vector = [] for i in range(0, len(loop_subnodes) - 1): - graph_vector.append(1.0 if pet.depends_ignore_readonly(loop_subnodes[i + 1], loop_subnodes[i], root) else 0.0) + graph_vector.append(1.0 if depends_ignore_readonly(pet, loop_subnodes[i + 1], loop_subnodes[i], root) else 0.0) pipeline_vector = [] for i in range(0, len(loop_subnodes) - 1): @@ -240,7 +244,7 @@ def __detect_pipeline(pet: PEGraphX, root: Node) -> float: min_weight = 1.0 for i in range(0, len(loop_subnodes) - 1): for j in range(i + 1, len(loop_subnodes)): - if pet.depends_ignore_readonly(loop_subnodes[i], loop_subnodes[j], root): + if depends_ignore_readonly(pet, loop_subnodes[i], loop_subnodes[j], root): # TODO whose corresponding entry in the graph matrix is nonzero? node_weight = 1 - (j - i) / (len(loop_subnodes) - 1) if min_weight > node_weight > 0: diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index d216dca69..bfb98a1d6 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -11,6 +11,13 @@ from typing import Dict, List, Optional, cast, Set, Tuple import warnings +from discopop_explorer.functions.PEGraph.properties.is_loop_index import is_loop_index +from discopop_explorer.functions.PEGraph.properties.is_readonly_inside_loop_body import is_readonly_inside_loop_body +from discopop_explorer.functions.PEGraph.queries.edges import in_edges, out_edges +from discopop_explorer.functions.PEGraph.queries.nodes import all_nodes +from discopop_explorer.functions.PEGraph.queries.subtree import subtree_of_type +from discopop_explorer.functions.PEGraph.queries.variables import get_variables +from discopop_explorer.functions.PEGraph.traversal.parent import get_parent_function from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore @@ -80,7 +87,7 @@ def run_detection( global global_pet global_pet = pet result: List[ReductionInfo] = [] - nodes = pet.all_nodes(LoopNode) + nodes = all_nodes(pet, LoopNode) nodes = cast(List[LoopNode], filter_for_hotspots(pet, cast(List[Node], nodes), hotspots)) @@ -126,13 +133,13 @@ def __detect_reduction(pet: PEGraphX, root: LoopNode) -> bool: :return: true if is reduction loop """ all_vars = [] - for node in pet.subtree_of_type(root, CUNode): + for node in subtree_of_type(pet, root, CUNode): all_vars.extend(node.local_vars) all_vars.extend(node.global_vars) # get required metadata loop_start_lines: List[LineID] = [] - root_children = pet.subtree_of_type(root, (CUNode, LoopNode)) + root_children = subtree_of_type(pet, root, (CUNode, LoopNode)) root_children_cus: List[CUNode] = [cast(CUNode, cu) for cu in root_children if cu.type == NodeType.CU] root_children_loops: List[LoopNode] = [cast(LoopNode, cu) for cu in root_children if cu.type == NodeType.LOOP] for v in root_children_loops: @@ -149,12 +156,12 @@ def __detect_reduction(pet: PEGraphX, root: LoopNode) -> bool: # get parents of loop parent_loops = __get_parent_loops(pet, root) - parent_function_lineid = pet.get_parent_function(root).start_position() + parent_function_lineid = get_parent_function(pet, root).start_position() called_functions_lineids = __get_called_functions(pet, root) # get variables which are defined inside the loop defined_inside_loop: List[Tuple[Variable, Set[MemoryRegion]]] = [] - tmp_loop_variables = pet.get_variables(root_children_cus) + tmp_loop_variables = get_variables(pet, root_children_cus) for var in tmp_loop_variables: if ":" in var.defLine: file_id = int(var.defLine.split(":")[0]) @@ -211,8 +218,8 @@ def __check_loop_dependencies( # get dependency edges between children nodes deps = set() for n in loop_children_ids: - deps.update([(s, t, d) for s, t, d in pet.in_edges(n, EdgeType.DATA) if s in loop_children_ids]) - deps.update([(s, t, d) for s, t, d in pet.out_edges(n, EdgeType.DATA) if t in loop_children_ids]) + deps.update([(s, t, d) for s, t, d in in_edges(pet, n, EdgeType.DATA) if s in loop_children_ids]) + deps.update([(s, t, d) for s, t, d in out_edges(pet, n, EdgeType.DATA) if t in loop_children_ids]) # get memory regions which are defined inside the loop memory_regions_defined_in_loop = set() @@ -221,7 +228,8 @@ def __check_loop_dependencies( for source, target, dep in deps: # check if targeted variable is readonly inside loop - if pet.is_readonly_inside_loop_body( + if is_readonly_inside_loop_body( + pet, dep, root_loop, root_children_cus, @@ -232,7 +240,7 @@ def __check_loop_dependencies( continue # check if targeted variable is loop index - if pet.is_loop_index(dep.var_name, loop_start_lines, root_children_cus): + if is_loop_index(pet, dep.var_name, loop_start_lines, root_children_cus): continue # ignore dependencies where either source or sink do not lie within root_loop @@ -320,11 +328,11 @@ def __get_parent_loops(pet: PEGraphX, root_loop: LoopNode) -> List[LineID]: parents.append(current) # process incoming child edges - for s, t, e in pet.in_edges(current, EdgeType.CHILD): + for s, t, e in in_edges(pet, current, EdgeType.CHILD): if s not in visited and s not in queue: queue.append(s) # process incoming call edges - for s, t, e in pet.in_edges(current, EdgeType.CALLSNODE): + for s, t, e in in_edges(pet, current, EdgeType.CALLSNODE): if s not in visited and s not in queue: queue.append(s) @@ -341,10 +349,10 @@ def __get_called_functions(pet: PEGraphX, root_loop: LoopNode) -> List[LineID]: current = queue.pop() visited.add(current) # get called functions - for s, t, e in pet.out_edges(current, EdgeType.CALLSNODE): + for s, t, e in out_edges(pet, current, EdgeType.CALLSNODE): called_functions.add(t) # add children to queue - for s, t, e in pet.out_edges(current, EdgeType.CHILD): + for s, t, e in out_edges(pet, current, EdgeType.CHILD): if t not in queue and t not in visited: queue.append(t) @@ -360,13 +368,13 @@ def __check_for_problematic_function_argument_access( # if so, return True. Else. return false # find accessed function argument for source - source_pf = pet.get_parent_function(pet.node_at(source)) + source_pf = get_parent_function(pet, pet.node_at(source)) source_accessed_pf_args = [a for a in source_pf.args if a.name == dep.var_name] if len(source_accessed_pf_args) == 0: return False # find accessed function argument for target - target_pf = pet.get_parent_function(pet.node_at(target)) + target_pf = get_parent_function(pet, pet.node_at(target)) target_accessed_pf_args = [a for a in target_pf.args if a.name == dep.var_name] if len(target_accessed_pf_args) == 0: return False diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py index a916f20f6..6ed5cb053 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py @@ -21,6 +21,14 @@ from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.DepType import DepType from discopop_explorer.classes.patterns.PatternInfo import PatternInfo +from discopop_explorer.functions.PEGraph.properties.is_reduction_var_by_name import is_reduction_var_by_name +from discopop_explorer.functions.PEGraph.queries.memory_regions import get_memory_regions +from discopop_explorer.functions.PEGraph.queries.reductions import get_reduction_sign +from discopop_explorer.functions.PEGraph.queries.subtree import get_left_right_subtree, subtree_of_type +from discopop_explorer.functions.PEGraph.queries.variables import get_undefined_variables_inside_loop, get_variables +from discopop_explorer.functions.PEGraph.traversal.children import direct_children +from discopop_explorer.functions.PEGraph.traversal.parent import get_parent_function +from discopop_explorer.functions.PEGraph.traversal.successors import direct_successors from discopop_explorer.utils import ( __get_dep_of_type as get_dep_of_type, ) @@ -284,11 +292,11 @@ def __get_constructs( clauses: List[str] = [] var_names: List[str] = [] modified_var_names: List[str] = [] - subnodes = pet.subtree_of_type(pet.node_at(self.node_id), CUNode) + subnodes = subtree_of_type(pet, pet.node_at(self.node_id), CUNode) if self.map_type_to: modified_var_names = [] for var in self.map_type_to: - memory_regions = pet.get_memory_regions(subnodes, var.name) + memory_regions = get_memory_regions(pet, subnodes, var.name) # get size of memory region memory_region_sizes = get_sizes_of_memory_regions( @@ -315,7 +323,7 @@ def __get_constructs( if self.map_type_from: modified_var_names = [] for var in self.map_type_from: - memory_regions = pet.get_memory_regions(subnodes, var.name) + memory_regions = get_memory_regions(pet, subnodes, var.name) # get size of memory region memory_region_sizes = get_sizes_of_memory_regions( @@ -340,7 +348,7 @@ def __get_constructs( if self.map_type_tofrom: modified_var_names = [] for var in self.map_type_tofrom: - memory_regions = pet.get_memory_regions(subnodes, var.name) + memory_regions = get_memory_regions(pet, subnodes, var.name) # get size of memory region memory_region_sizes = get_sizes_of_memory_regions( @@ -365,7 +373,7 @@ def __get_constructs( if self.map_type_alloc: modified_var_names = [] for var in self.map_type_alloc: - memory_regions = pet.get_memory_regions(subnodes, var.name) + memory_regions = get_memory_regions(pet, subnodes, var.name) # get size of memory region memory_region_sizes = get_sizes_of_memory_regions( @@ -413,7 +421,7 @@ def __get_constructs( ) ) # get used global variables - cu_nodes: List[CUNode] = pet.subtree_of_type(fn_node, CUNode) + cu_nodes: List[CUNode] = subtree_of_type(pet, fn_node, CUNode) tmp_global_vars: Set[Variable] = set() for cu_node in cu_nodes: tmp_global_vars.update(cu_node.global_vars) @@ -480,7 +488,7 @@ def getDataStr(self, pet: PEGraphX) -> str: # loops including their iteration numbers. n: LoopNode = cast(LoopNode, map_node(pet, self.nodeID)) total_i: int = n.loop_iterations - for cn_id in pet.direct_children(n): + for cn_id in direct_children(pet, n): if cn_id.type == 2: # type loop ss += self.__add_sub_loops_rec(pet, cn_id.id, total_i) return ss @@ -492,9 +500,9 @@ def classifyLoopVars(self, pet: PEGraphX, loop: LoopNode) -> None: :return: """ reduction = [] - lst = pet.get_left_right_subtree(loop, False) - rst = pet.get_left_right_subtree(loop, True) - sub = pet.subtree_of_type(loop, CUNode) + lst = get_left_right_subtree(pet, loop, False) + rst = get_left_right_subtree(pet, loop, True) + sub = subtree_of_type(pet, loop, CUNode) raw = set() war = set() @@ -511,7 +519,7 @@ def classifyLoopVars(self, pet: PEGraphX, loop: LoopNode) -> None: rev_raw.update(get_dep_of_type(pet, sub_node, DepType.RAW, True)) # global vars need to be considered as well since mapping / updates may be required - vars = pet.get_undefined_variables_inside_loop(loop, include_global_vars=True) + vars = get_undefined_variables_inside_loop(pet, loop, include_global_vars=True) _, private_vars, _, _, _ = classify_loop_variables(pet, loop) @@ -529,8 +537,8 @@ def classifyLoopVars(self, pet: PEGraphX, loop: LoopNode) -> None: continue if is_loop_index2(pet, loop, var.name): continue - elif loop.reduction and pet.is_reduction_var(loop.start_position(), var.name): - var.operation = pet.get_reduction_sign(loop.start_position(), var.name) + elif loop.reduction and is_reduction_var_by_name(pet, loop.start_position(), var.name): + var.operation = get_reduction_sign(pet, loop.start_position(), var.name) reduction.append(var) # TODO grouping @@ -541,7 +549,7 @@ def classifyLoopVars(self, pet: PEGraphX, loop: LoopNode) -> None: # "manual" triggering of "map(to)" required for true global variables since initialization of global # variables might not occur in dependencies since the initializations are not instrumented is_global(var.name, sub) - and not pet.get_parent_function(loop).contains_line(var.defLine) + and not get_parent_function(pet, loop).contains_line(var.defLine) ) ): if is_readonly(vars[var], war, waw, rev_raw): @@ -563,8 +571,8 @@ def classifyLoopVars(self, pet: PEGraphX, loop: LoopNode) -> None: pass # use known variables to reconstruct the correct variable names from the classified memory regions - left_subtree_without_called_nodes = pet.get_left_right_subtree(loop, False, ignore_called_nodes=True) - prior_known_vars = pet.get_variables(left_subtree_without_called_nodes) + left_subtree_without_called_nodes = get_left_right_subtree(pet, loop, False, ignore_called_nodes=True) + prior_known_vars = get_variables(pet, left_subtree_without_called_nodes) # get memory regions which are initialized in the loop and treat them like prior known vars wrt. de-aliasing initilized_in_loop = get_initialized_memory_regions_in(pet, sub) combined_know_vars: Dict[Variable, Set[MemoryRegion]] = dict() @@ -619,7 +627,7 @@ def getNestedLoops(self, pet: PEGraphX, node_id: NodeID) -> None: # extend the string stream with this information and scan all child nodes to # identify and process further nested loops - for cn_id in pet.direct_children(n): + for cn_id in direct_children(pet, n): if cn_id.type == 2: # type loop self.nestedLoops.add(cn_id.id) self.getNestedLoops(pet, cn_id.id) @@ -632,7 +640,7 @@ def getNextLoop(self, pet: PEGraphX, node_id: NodeID) -> None: """ n = map_node(pet, node_id) endLine = 0 - for children in pet.direct_children(n): + for children in direct_children(pet, n): if children.end_line > endLine: endLine = children.end_line @@ -649,9 +657,9 @@ def setCollapseClause(self, pet: PEGraphX, node_id: NodeID, res: DetectionResult loop_entry_node = cast(LoopNode, pet.node_at(node_id)).get_entry_node(pet) if loop_entry_node is None: - loop_entry_node = pet.direct_children(pet.node_at(node_id))[0] + loop_entry_node = direct_children(pet, pet.node_at(node_id))[0] - for cn_id in pet.direct_children(n): + for cn_id in direct_children(pet, n): if cn_id.type == 2: # check for loop node contained in the loop body if cn_id.end_line <= n.end_line: # todo not true if loop bodies are terminated by braces # only consider child as collapsible, if it is a do-all loop @@ -661,12 +669,12 @@ def setCollapseClause(self, pet: PEGraphX, node_id: NodeID, res: DetectionResult # information from the LLVM debug information # check if distance between first CU of node_id and cn_id is 2 steps on the successor graph potentials: Set[Node] = set() - for succ1 in pet.direct_successors(loop_entry_node): - for succ2 in pet.direct_successors(succ1): + for succ1 in direct_successors(pet, loop_entry_node): + for succ2 in direct_successors(pet, succ1): potentials.add(succ2) if cast(LoopNode, cn_id).get_entry_node(pet) in potentials: # perfect nesting possible. allow collapsing the loops, if root loop has no other children - if len(pet.direct_children(pet.node_at(node_id))) == 5: + if len(direct_children(pet, pet.node_at(node_id))) == 5: # 2 children for loop condition and body # 1 child is the collapsible loop # 2 children for loop end and increment @@ -738,7 +746,7 @@ def __add_sub_loops_rec(self, pet: PEGraphX, node_id: NodeID, top_loop_iteration # extend the string stream with this information and scan all child nodes to # identify and process further nested loops ss: str = " " + str(ll) + "-" + str(i_cnt) - for cn_id in pet.direct_children(n): + for cn_id in direct_children(pet, n): if cn_id.type == 2: ss += self.__add_sub_loops_rec(pet, cn_id.id, top_loop_iterations) return ss diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py index 8775f2781..4612a34d7 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPUMemory.py @@ -20,6 +20,7 @@ from discopop_explorer.classes.PEGraph.Dependency import Dependency from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.DepType import DepType +from discopop_explorer.functions.PEGraph.queries.subtree import subtree_of_type from discopop_explorer.utils import is_func_arg, is_global, __get_dep_of_type as get_dep_of_type from discopop_explorer.classes.variable import Variable @@ -78,11 +79,11 @@ def getCalledFunctions( :param dummyFunctions: :return: """ - sub_func = pet.subtree_of_type(node, FunctionNode) + sub_func = subtree_of_type(pet, node, FunctionNode) for f in sub_func: calledFunctions.add(f.id) # unnecessary in this i think - sub_dummy = pet.subtree_of_type(node, DummyNode) + sub_dummy = subtree_of_type(pet, node, DummyNode) for d in sub_dummy: dummyFunctions.add(d.id) diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py index 4611029b8..3045a75ee 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py @@ -21,6 +21,9 @@ from discopop_explorer.enums.DepType import DepType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.classes.variable import Variable +from discopop_explorer.functions.PEGraph.queries.edges import in_edges, out_edges +from discopop_explorer.functions.PEGraph.queries.subtree import subtree_of_type +from discopop_explorer.functions.PEGraph.traversal.children import direct_children from discopop_explorer.pattern_detectors.simple_gpu_patterns.GPULoop import GPULoopPattern from discopop_explorer.pattern_detectors.simple_gpu_patterns.GPUMemory import map_node from discopop_explorer.classes.patterns.PatternInfo import PatternInfo @@ -98,7 +101,7 @@ def get_entry_cus(self, pet: PEGraphX) -> List[str]: entry_cus: List[str] = [] for contained_cu_id in self.contained_cu_ids: # check if contained_cu has only predecessors inside the gpu region - for predecessor_id, _, _ in pet.in_edges(contained_cu_id, EdgeType.SUCCESSOR): + for predecessor_id, _, _ in in_edges(pet, contained_cu_id, EdgeType.SUCCESSOR): if predecessor_id not in self.contained_cu_ids: # found entry node entry_cus.append(contained_cu_id) @@ -114,7 +117,7 @@ def get_exit_cus(self, pet: PEGraphX) -> Tuple[List[str], List[str]]: outside_cus: List[str] = [] for contained_cu_id in self.contained_cu_ids: # check if contained_cu_id has only successors inside the gpu region - for _, successor_id, _ in pet.out_edges(contained_cu_id, EdgeType.SUCCESSOR): + for _, successor_id, _ in out_edges(pet, contained_cu_id, EdgeType.SUCCESSOR): if successor_id not in self.contained_cu_ids: # found exit node contained_exit_cus.append(contained_cu_id) @@ -182,11 +185,11 @@ def reachableCUs(self, cuID: NodeID, nextCUID: NodeID) -> bool: if nextLoop.type != 2: return False - loopFirstChild: Node = self.pet.direct_children(loop)[0] - CUIDsofLoop = self.pet.out_edges(loopFirstChild.id, EdgeType.SUCCESSOR) + loopFirstChild: Node = direct_children(self.pet, loop)[0] + CUIDsofLoop = out_edges(self.pet, loopFirstChild.id, EdgeType.SUCCESSOR) lastCUofLoop = map_node(self.pet, CUIDsofLoop[-1][1]) - nextLoopFirstChild: Node = self.pet.direct_children(nextLoop)[0] - successors = self.pet.out_edges(lastCUofLoop.id, EdgeType.SUCCESSOR) + nextLoopFirstChild: Node = direct_children(self.pet, nextLoop)[0] + successors = out_edges(self.pet, lastCUofLoop.id, EdgeType.SUCCESSOR) if successors: if nextLoopFirstChild.id == successors[0][1]: return True @@ -239,10 +242,10 @@ def determineDataMapping(self) -> None: loop_node: LoopNode = cast(LoopNode, self.pet.node_at(loop_id)) gpu_lp: GPULoopPattern = [p for p in self.gpu_loop_patterns if p.parentLoop == loop_id][0] region_loop_patterns.append(gpu_lp) - region_cus += [cu for cu in self.pet.subtree_of_type(loop_node) if cu not in region_cus] + region_cus += [cu for cu in subtree_of_type(self.pet, loop_node) if cu not in region_cus] # add loop initialization to region cus (predecessor of first child of loop, if positions are suitable) - loop_entry_cu = self.pet.out_edges(loop_id, EdgeType.CHILD)[0][1] - predecessors = [s for s, t, d in self.pet.in_edges(loop_entry_cu, EdgeType.SUCCESSOR)] + loop_entry_cu = out_edges(self.pet, loop_id, EdgeType.CHILD)[0][1] + predecessors = [s for s, t, d in in_edges(self.pet, loop_entry_cu, EdgeType.SUCCESSOR)] for predecessor_id in predecessors: predecessor_node = self.pet.node_at(predecessor_id) if ( @@ -262,7 +265,7 @@ def determineDataMapping(self) -> None: # determine variables which are written outside the region and read inside consumed_vars: List[str] = [] for cu in region_cus: - in_dep_edges = self.pet.out_edges(cu.id, EdgeType.DATA) + in_dep_edges = out_edges(self.pet, cu.id, EdgeType.DATA) # var is consumed, if incoming RAW dep exists for sink_cu_id, source_cu_id, dep in in_dep_edges: @@ -279,7 +282,7 @@ def determineDataMapping(self) -> None: # determine variables which are read afterwards and written in the region produced_vars: List[str] = [] for cu in region_cus: - out_dep_edges = self.pet.in_edges(cu.id, EdgeType.DATA) + out_dep_edges = in_edges(self.pet, cu.id, EdgeType.DATA) # var is produced, if outgoing RAW or WAW dep exists for sink_cu_id, source_cu_id, dep in out_dep_edges: # unpack dep for sake of clarity @@ -480,7 +483,7 @@ def get_gpu_region_info(self, pet: PEGraphX, project_folder_path: str) -> List[G device_cu_ids = self.cu_ids_by_region[tuple(region)] for loop in contained_loop_patterns: for func_node_id in loop.called_functions: - for child in pet.direct_children(pet.node_at(func_node_id)): + for child in direct_children(pet, pet.node_at(func_node_id)): device_cu_ids.append(child.id) device_cu_ids = list(set(device_cu_ids)) diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py index 0c70288fe..0e52f51ce 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py @@ -14,6 +14,7 @@ from discopop_explorer.classes.PEGraph.LoopNode import LoopNode from discopop_explorer.aliases.LineID import LineID from discopop_explorer.classes.patterns.PatternInfo import PatternInfo +from discopop_explorer.functions.PEGraph.queries.nodes import all_nodes from discopop_explorer.pattern_detectors.simple_gpu_patterns.GPULoop import GPULoopPattern from discopop_explorer.pattern_detectors.simple_gpu_patterns.GPURegions import ( GPURegions, @@ -32,10 +33,10 @@ def run_detection(pet: PEGraphX, res: DetectionResult, project_folder_path: str) """ gpu_patterns: List[GPULoopPattern] = [] - loop_node_count = len(pet.all_nodes(type=LoopNode)) + loop_node_count = len(all_nodes(pet, type=LoopNode)) print("\tcreate gpu patterns...") with alive_bar(loop_node_count) as progress_bar: - for node in pet.all_nodes(type=LoopNode): + for node in all_nodes(pet, type=LoopNode): # check for lastprivates, since they are not supported by the suggested pragma: # pragma omp target teams distribute # todo: instead of omitting, suggest #pragma omp target parallel for instead diff --git a/discopop_explorer/pattern_detectors/task_parallelism/filter.py b/discopop_explorer/pattern_detectors/task_parallelism/filter.py index 9d283f46d..72f3c04eb 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/filter.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/filter.py @@ -14,6 +14,8 @@ from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.classes.patterns.PatternInfo import PatternInfo +from discopop_explorer.functions.PEGraph.queries.edges import in_edges +from discopop_explorer.functions.PEGraph.queries.nodes import all_nodes from discopop_explorer.pattern_detectors.task_parallelism.classes import ( TaskParallelismInfo, ParallelRegionInfo, @@ -252,7 +254,7 @@ def __reverse_reachable_w_o_breaker( return False recursion_result = False # start recursion for each incoming edge - for tmp_e in pet.in_edges(root.id, EdgeType.SUCCESSOR): + for tmp_e in in_edges(pet, root.id, EdgeType.SUCCESSOR): recursion_result = recursion_result or __reverse_reachable_w_o_breaker( pet, pet.node_at(tmp_e[0]), target, breaker_cu, visited ) @@ -341,7 +343,7 @@ def __filter_sharing_clause( to_be_removed.append(var) continue # 2. check if task suggestion is child of same nodes as var_def_cu - for in_child_edge in pet.in_edges(var_def_cu.id, [EdgeType.CHILD, EdgeType.CALLSNODE]): + for in_child_edge in in_edges(pet, var_def_cu.id, [EdgeType.CHILD, EdgeType.CALLSNODE]): parent_cu = pet.node_at(in_child_edge[0]) # check if task suggestion cu is reachable from parent via child edges if not check_reachability(pet, suggestion._node, parent_cu, [EdgeType.CHILD]): @@ -457,7 +459,7 @@ def __filter_in_dependencies( # successor + child graph # get CU containing line_num - for cu_node in pet.all_nodes(CUNode): + for cu_node in all_nodes(pet, CUNode): file_id = suggestion._node.start_position().split(":")[0] test_line = file_id + ":" + line_num # check if line_num is contained in cu_node @@ -522,7 +524,7 @@ def __filter_out_dependencies( # successor + child graph # get CU containing line_num - for cu_node in pet.all_nodes(CUNode): + for cu_node in all_nodes(pet, CUNode): file_id = suggestion._node.start_position().split(":")[0] test_line = file_id + ":" + line_num # check if line_num is contained in cu_node @@ -593,7 +595,7 @@ def __filter_in_out_dependencies( # successor + child graph # get CU containing line_num - for cu_node in pet.all_nodes(CUNode): + for cu_node in all_nodes(pet, CUNode): file_id = suggestion._node.start_position().split(":")[0] test_line = file_id + ":" + line_num # check if line_num is contained in cu_node @@ -617,7 +619,7 @@ def __filter_in_out_dependencies( # successor + child graph # get CU containing line_num - for cu_node in pet.all_nodes(CUNode): + for cu_node in all_nodes(pet, CUNode): file_id = suggestion._node.start_position().split(":")[0] test_line = file_id + ":" + line_num # check if line_num is contained in cu_node diff --git a/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py b/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py index ea74059e4..cbf3993fb 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/postprocessor.py @@ -12,6 +12,7 @@ from discopop_explorer.classes.PEGraph.Node import Node from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.classes.patterns.PatternInfo import PatternInfo +from discopop_explorer.functions.PEGraph.queries.edges import in_edges, out_edges from discopop_explorer.pattern_detectors.task_parallelism.classes import ( TaskParallelismInfo, ParallelRegionInfo, @@ -41,16 +42,16 @@ def group_task_suggestions(pet: PEGraphX, suggestions: List[PatternInfo]) -> Lis # mark taskwait suggestion with own id tws.task_group.append(task_group_id) relatives: List[Node] = [tws._node] - queue: List[Node] = [pet.node_at(in_e[0]) for in_e in pet.in_edges(tws._node.id, EdgeType.SUCCESSOR)] + queue: List[Node] = [pet.node_at(in_e[0]) for in_e in in_edges(pet, tws._node.id, EdgeType.SUCCESSOR)] while len(queue) > 0: cur = queue.pop(0) if cur.tp_contains_taskwait: continue relatives.append(cur) - for in_edge in pet.in_edges(cur.id, EdgeType.SUCCESSOR): + for in_edge in in_edges(pet, cur.id, EdgeType.SUCCESSOR): if pet.node_at(in_edge[0]) not in relatives + queue: queue.append(pet.node_at(in_edge[0])) - for out_edge in pet.out_edges(cur.id, EdgeType.SUCCESSOR): + for out_edge in out_edges(pet, cur.id, EdgeType.SUCCESSOR): if pet.node_at(out_edge[1]) not in relatives + queue: queue.append(pet.node_at(out_edge[1])) diff --git a/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py b/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py index 8077060e0..aeec4e4aa 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py @@ -14,6 +14,8 @@ from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.classes.PEGraph.LoopNode import LoopNode +from discopop_explorer.functions.PEGraph.queries.nodes import all_nodes +from discopop_explorer.functions.PEGraph.traversal.children import direct_children_or_called_nodes from discopop_explorer.pattern_detectors.task_parallelism.tp_utils import line_contained_in_region @@ -388,8 +390,8 @@ def check_loop_scopes(pet: PEGraphX) -> None: """Checks if the scope of loop CUs matches these of their children. Corrects the scope of the loop CU (expand only) if necessary :param pet: PET graph""" - for loop_cu in pet.all_nodes(LoopNode): - for child in pet.direct_children_or_called_nodes(loop_cu): + for loop_cu in all_nodes(pet, LoopNode): + for child in direct_children_or_called_nodes(pet, loop_cu): if not line_contained_in_region(child.start_position(), loop_cu.start_position(), loop_cu.end_position()): # expand loop_cu start_position upwards if child.start_line < loop_cu.start_line and loop_cu.file_id == child.file_id: diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py index 97d05d07c..d2161a9f7 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/auxiliary.py @@ -14,6 +14,7 @@ from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.classes.patterns.PatternInfo import PatternInfo +from discopop_explorer.functions.PEGraph.queries.edges import in_edges from discopop_explorer.pattern_detectors.task_parallelism.classes import ( TaskParallelismInfo, ParallelRegionInfo, @@ -189,7 +190,7 @@ def combine_omittable_cus(pet: PEGraphX, suggestions: List[PatternInfo]) -> List # successor graph of a node containing a task suggestion useful_omittable_suggestions = [] for oms in omittable_suggestions: - in_succ_edges = [(s, t, e) for s, t, e in pet.in_edges(oms._node.id) if e.etype == EdgeType.SUCCESSOR] + in_succ_edges = [(s, t, e) for s, t, e in in_edges(pet, oms._node.id) if e.etype == EdgeType.SUCCESSOR] parent_task_nodes = [pet.node_at(e[0]) for e in in_succ_edges if pet.node_at(e[0]).tp_contains_task is True] if len(parent_task_nodes) != 0: useful_omittable_suggestions.append(oms) diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py index 10ed929cb..3b9455822 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py @@ -15,6 +15,9 @@ from discopop_explorer.enums.NodeType import NodeType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.classes.patterns.PatternInfo import PatternInfo +from discopop_explorer.functions.PEGraph.queries.edges import in_edges, out_edges +from discopop_explorer.functions.PEGraph.queries.nodes import all_nodes +from discopop_explorer.functions.PEGraph.traversal.successors import direct_successors from discopop_explorer.pattern_detectors.task_parallelism.classes import ( ParallelRegionInfo, OmittableCuInfo, @@ -58,20 +61,20 @@ def detect_barrier_suggestions(pet: PEGraphX, suggestions: List[PatternInfo]) -> transformation_happened = True # let run until convergence - queue = list(pet.all_nodes()) + queue = list(all_nodes(pet)) while transformation_happened or len(queue) > 0: transformation_happened = False v = queue.pop(0) # check step 1 out_dep_edges = [ - (s, t, e) for s, t, e in pet.out_edges(v.id) if e.etype == EdgeType.DATA and pet.node_at(t) != v + (s, t, e) for s, t, e in out_edges(pet, v.id) if e.etype == EdgeType.DATA and pet.node_at(t) != v ] # ignore cyclic dependencies on the same variable to_remove = [] for dep_edge in out_dep_edges: targets_cyclic_dep_edges = [ (s, t, e) - for s, t, e in pet.out_edges(dep_edge[1]) + for s, t, e in out_edges(pet, dep_edge[1]) if e.etype == EdgeType.DATA and t == dep_edge[0] and e.var_name == dep_edge[2].var_name ] if len(targets_cyclic_dep_edges) != 0: @@ -165,7 +168,7 @@ def detect_barrier_suggestions(pet: PEGraphX, suggestions: List[PatternInfo]) -> # append neighbors of modified node to queue if transformation_happened: in_dep_edges = [ - (s, t, e) for s, t, e in pet.in_edges(v.id) if e.etype == EdgeType.DATA and pet.node_at(s) != v + (s, t, e) for s, t, e in in_edges(pet, v.id) if e.etype == EdgeType.DATA and pet.node_at(s) != v ] for e in out_dep_edges: queue.append(pet.node_at(e[1])) @@ -254,7 +257,7 @@ def __check_dependences_and_predecessors( else: violation = True # check if node is a direct successor of an omittable node or a task node - in_succ_edges = [(s, t, e) for (s, t, e) in pet.in_edges(cur_cu.id) if e.etype == EdgeType.SUCCESSOR] + in_succ_edges = [(s, t, e) for (s, t, e) in in_edges(pet, cur_cu.id) if e.etype == EdgeType.SUCCESSOR] is_successor = False for e in in_succ_edges: if pet.node_at(e[0]).tp_omittable is True: @@ -330,7 +333,7 @@ def suggest_barriers_for_uncovered_tasks_before_return( targets.append(current_node) continue # append direct successors to targets, if not in visited - successors = pet.direct_successors(current_node) + successors = direct_successors(pet, current_node) successors = [ds for ds in successors if ds not in visited] queue = queue + successors # suggest taskwait prior to return if needed @@ -385,7 +388,7 @@ def validate_barriers(pet: PEGraphX, suggestions: List[PatternInfo]) -> List[Pat # create "path lists" for each incoming successor edge in_succ_edges = [ (s, t, e) - for s, t, e in pet.in_edges(bs._node.id) + for s, t, e in in_edges(pet, bs._node.id) if e.etype == EdgeType.SUCCESSOR and pet.node_at(s) != bs._node ] predecessors_dict = dict() @@ -397,7 +400,7 @@ def validate_barriers(pet: PEGraphX, suggestions: List[PatternInfo]) -> List[Pat # for those paths that contain the dependence target CU out_dep_edges = [ (s, t, e) - for s, t, e in pet.out_edges(bs._node.id) + for s, t, e in out_edges(pet, bs._node.id) if e.etype == EdgeType.DATA and pet.node_at(t) != bs._node ] dependence_count_dict = dict() @@ -455,7 +458,7 @@ def suggest_missing_barriers_for_global_vars(pet: PEGraphX, suggestions: List[Pa visited_nodes = [task_sug._node] out_succ_edges = [ (s, t, e) - for s, t, e in pet.out_edges(task_sug._node.id) + for s, t, e in out_edges(pet, task_sug._node.id) if e.etype == EdgeType.SUCCESSOR and pet.node_at(t) != task_sug._node ] queue = out_succ_edges @@ -502,7 +505,7 @@ def suggest_missing_barriers_for_global_vars(pet: PEGraphX, suggestions: List[Pa # append current nodes outgoing successor edges to queue target_out_succ_edges = [ (s, t, e) - for s, t, e in pet.out_edges(pet.node_at(succ_edge[1]).id) + for s, t, e in out_edges(pet, pet.node_at(succ_edge[1]).id) if e.etype == EdgeType.SUCCESSOR and pet.node_at(t) != pet.node_at(succ_edge[1]) ] queue = list(set(queue + target_out_succ_edges)) diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py index 5490b9f48..1360c1162 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/data_sharing_clauses.py @@ -12,6 +12,7 @@ from discopop_explorer.classes.PEGraph.FunctionNode import FunctionNode from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.classes.patterns.PatternInfo import PatternInfo +from discopop_explorer.functions.PEGraph.queries.edges import in_edges from discopop_explorer.pattern_detectors.task_parallelism.classes import ( TaskParallelismInfo, TPIType, @@ -34,7 +35,7 @@ def suggest_shared_clauses_for_all_tasks_in_function_body( # iterate over parent function(s) for parent_function in [ pet.node_at(e[0]) - for e in pet.in_edges(ts._node.id, EdgeType.CHILD) + for e in in_edges(pet, ts._node.id, EdgeType.CHILD) if isinstance(pet.node_at(e[0]), FunctionNode) ]: # get task suggestions in parent functions scope diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py index 88ebde17e..113598148 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py @@ -19,6 +19,12 @@ from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.classes.patterns.PatternInfo import PatternInfo +from discopop_explorer.functions.PEGraph.queries.edges import in_edges, out_edges +from discopop_explorer.functions.PEGraph.queries.nodes import all_nodes +from discopop_explorer.functions.PEGraph.traversal.children import ( + direct_children_or_called_nodes, + direct_children_or_called_nodes_of_type, +) from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import VarName from discopop_explorer.pattern_detectors.task_parallelism.alias_detection import ( get_alias_information as get_alias_detection_result, @@ -208,7 +214,7 @@ def get_alias_information( if int(recursive_function_call_line.split(":")[1]) == int(ts.pragma_line): # correct function call found # find corresponding function CU - for tmp_func_cu in pet.all_nodes(FunctionNode): + for tmp_func_cu in all_nodes(pet, FunctionNode): if tmp_func_cu.name == recursive_function_call_entry_split[0]: called_function_cu_id = tmp_func_cu.id # get aliases for parameters @@ -423,20 +429,20 @@ def __get_potential_parent_functions(pet: PEGraphX, sug: TaskParallelismInfo) -> :return: List of potential parents of sug (Function CU Nodes)""" potential_parent_functions = [ pet.node_at(e[0]) - for e in pet.in_edges(sug._node.id, EdgeType.CHILD) + for e in in_edges(pet, sug._node.id, EdgeType.CHILD) if isinstance(pet.node_at(e[0]), FunctionNode) ] if not potential_parent_functions: # perform BFS search on incoming CHILD edges to find closest parent function, # i.e. function which contains the CU. - queue = [pet.node_at(e[0]) for e in pet.in_edges(sug._node.id, EdgeType.CHILD)] + queue = [pet.node_at(e[0]) for e in in_edges(pet, sug._node.id, EdgeType.CHILD)] found_parent = None while len(queue) > 0 or not found_parent: current = queue.pop(0) if isinstance(current, FunctionNode): found_parent = current break - queue += [pet.node_at(e[0]) for e in pet.in_edges(current.id, EdgeType.CHILD)] + queue += [pet.node_at(e[0]) for e in in_edges(pet, current.id, EdgeType.CHILD)] potential_parent_functions = [found_parent] return potential_parent_functions @@ -447,7 +453,7 @@ def __get_potential_children_of_function(pet: PEGraphX, parent_function: Node) - :param pet: PET Graph :param parent_function: function to be analyzed :return: List of CUNodes contained in functions body.""" - queue = pet.direct_children_or_called_nodes(parent_function) + queue = direct_children_or_called_nodes(pet, parent_function) potential_children = [] visited = [] while queue: @@ -464,7 +470,7 @@ def __get_potential_children_of_function(pet: PEGraphX, parent_function: Node) - parent_function.end_position(), ): potential_children.append(cur_potential_child) - for tmp_child in pet.direct_children_or_called_nodes(cur_potential_child): + for tmp_child in direct_children_or_called_nodes(pet, cur_potential_child): if tmp_child not in queue and tmp_child not in potential_children and tmp_child not in visited: queue.append(tmp_child) return potential_children @@ -718,7 +724,7 @@ def get_alias_for_parameter_at_position( # find function calls which use the parameter # iterate over CUs - for cu in [pet.node_at(cuid) for cuid in [e[1] for e in pet.out_edges(function.id)]]: + for cu in [pet.node_at(cuid) for cuid in [e[1] for e in out_edges(pet, function.id)]]: # iterate over children of CU and retrieve called functions called_functions = get_called_functions_recursively(pet, cu, [], called_function_cache) called_functions = list(set(called_functions)) @@ -897,21 +903,21 @@ def get_function_call_parameter_rw_information( if int(call_position.split(":")[1]) == lower_line_num: # correct function call found # find corresponding function CU - for tmp_func_cu in pet.all_nodes(FunctionNode): + for tmp_func_cu in all_nodes(pet, FunctionNode): if tmp_func_cu.name == called_function_name: called_function_cu_id = tmp_func_cu.id elif not equal_lower_line_num and greater_lower_line_num: if int(call_position.split(":")[1]) > lower_line_num: # correct function call found # find corresponding function CU - for tmp_func_cu in pet.all_nodes(FunctionNode): + for tmp_func_cu in all_nodes(pet, FunctionNode): if tmp_func_cu.name == called_function_name: called_function_cu_id = tmp_func_cu.id else: if int(call_position.split(":")[1]) >= lower_line_num: # correct function call found # find corresponding function CU - for tmp_func_cu in pet.all_nodes(FunctionNode): + for tmp_func_cu in all_nodes(pet, FunctionNode): if tmp_func_cu.name == called_function_name: called_function_cu_id = tmp_func_cu.id if called_function_cu_id is None: @@ -1059,7 +1065,7 @@ def get_function_call_parameter_rw_information_recursion_step( # get potential children of called function recursively_visited.append(called_function_cu) - queue_1 = pet.direct_children_or_called_nodes(called_function_cu) + queue_1 = direct_children_or_called_nodes(pet, called_function_cu) potential_children = [] visited = [] while queue_1: @@ -1077,7 +1083,7 @@ def get_function_call_parameter_rw_information_recursion_step( ): if cur_potential_child not in potential_children: potential_children.append(cur_potential_child) - for tmp_child in pet.direct_children_or_called_nodes(cur_potential_child): + for tmp_child in direct_children_or_called_nodes(pet, cur_potential_child): if tmp_child not in queue_1 and tmp_child not in potential_children and tmp_child not in visited: queue_1.append(tmp_child) @@ -1098,7 +1104,7 @@ def get_function_call_parameter_rw_information_recursion_step( ) ]: # find called functions - for child_func in pet.direct_children_or_called_nodes_of_type(child, FunctionNode): + for child_func in direct_children_or_called_nodes_of_type(pet, child, FunctionNode): # apply __get_function_call_parameter_rw_information if child not in recursively_visited: ret_val = get_function_call_parameter_rw_information( @@ -1161,12 +1167,12 @@ def get_function_call_parameter_rw_information_recursion_step( ): function_internal_cu_nodes.append(cur) # add children to queue - for cur_child in pet.direct_children_or_called_nodes(cur): + for cur_child in direct_children_or_called_nodes(pet, cur): if cur_child not in function_internal_cu_nodes and cur_child not in queue: queue.append(cur_child) for child_cu in function_internal_cu_nodes: - child_in_deps = pet.in_edges(child_cu.id, EdgeType.DATA) - child_out_deps = pet.out_edges(child_cu.id, EdgeType.DATA) + child_in_deps = in_edges(pet, child_cu.id, EdgeType.DATA) + child_out_deps = out_edges(pet, child_cu.id, EdgeType.DATA) dep_var_names = [x[2].var_name for x in child_in_deps + child_out_deps] dep_var_names_not_none = [x for x in dep_var_names if x is not None] dep_var_names_not_none = [x.replace(".addr", "") for x in dep_var_names_not_none] diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py index d701c76d9..fc16c2901 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py @@ -19,6 +19,10 @@ from discopop_explorer.enums.MWType import MWType from discopop_explorer.enums.EdgeType import EdgeType from discopop_explorer.classes.patterns.PatternInfo import PatternInfo +from discopop_explorer.functions.PEGraph.queries.edges import in_edges, out_edges +from discopop_explorer.functions.PEGraph.queries.nodes import all_nodes +from discopop_explorer.functions.PEGraph.traversal.children import direct_children_or_called_nodes +from discopop_explorer.functions.PEGraph.traversal.successors import direct_successors from discopop_explorer.pattern_detectors.task_parallelism.classes import ( TaskParallelismInfo, TPIType, @@ -50,7 +54,7 @@ def detect_task_suggestions(pet: PEGraphX) -> List[PatternInfo]: func_cus: List[Node] = [] - for v in pet.all_nodes(): + for v in all_nodes(pet): if v.mw_type == MWType.WORKER: worker_cus.append(v) if v.mw_type == MWType.BARRIER: @@ -67,7 +71,7 @@ def detect_task_suggestions(pet: PEGraphX) -> List[PatternInfo]: # get line number of first dependency. suggest taskwait prior to that first_dependency_line = v.end_position() first_dependency_line_number = first_dependency_line[first_dependency_line.index(":") + 1 :] - for s, t, e in pet.out_edges(v.id): + for s, t, e in out_edges(pet, v.id): if e.etype == EdgeType.DATA: dep_line = cast(LineID, e.sink_line) dep_line_number = dep_line[dep_line.index(":") + 1 :] @@ -83,7 +87,7 @@ def detect_task_suggestions(pet: PEGraphX) -> List[PatternInfo]: suggestions[v.start_position()].append(tmp_suggestion) # SUGGEST TASKS - for vx in pet.all_nodes(): + for vx in all_nodes(pet): # iterate over all entries in recursiveFunctionCalls # in order to find task suggestions for i in range(0, len(vx.recursive_function_calls)): @@ -156,7 +160,7 @@ def correct_task_suggestions_in_loop_body(pet: PEGraphX, suggestions: List[Patte for ts in task_suggestions: found_critical_cus: List[Node] = [] found_atomic_cus: List[Node] = [] - for loop_cu in pet.all_nodes(LoopNode): + for loop_cu in all_nodes(pet, LoopNode): # check if task suggestion inside do-all loop exists if line_contained_in_region(ts._node.start_position(), loop_cu.start_position(), loop_cu.end_position()): @@ -167,7 +171,7 @@ def find_taskwaits(cu_node: Node, visited: List[Node]) -> List[Node]: visited.append(cu_node) for succ_cu_node in [ pet.node_at(t) - for s, t, e in pet.out_edges(cu_node.id) + for s, t, e in out_edges(pet, cu_node.id) if e.etype == EdgeType.SUCCESSOR and pet.node_at(t) != cu_node ]: if succ_cu_node not in visited: @@ -217,7 +221,7 @@ def find_taskwaits(cu_node: Node, visited: List[Node]) -> List[Node]: # move pragma task line to beginning of loop body (i.e. make the entire loop body a task) # set task region lines accordingly # if ts._node is a direct child of loop_cu - if loop_cu.id in [e[0] for e in pet.in_edges(ts._node.id, EdgeType.CHILD)]: + if loop_cu.id in [e[0] for e in in_edges(pet, ts._node.id, EdgeType.CHILD)]: print( "Moving Pragma from: ", ts.pragma_line, @@ -233,9 +237,9 @@ def find_taskwaits(cu_node: Node, visited: List[Node]) -> List[Node]: # protect RAW-Writes to shared variables with critical section # i.e. find in-deps to shared variables and suggest critical section around CUs # containing such cases - for loop_cu_child in pet.direct_children_or_called_nodes(loop_cu): + for loop_cu_child in direct_children_or_called_nodes(pet, loop_cu): for in_dep_var_name in list( - set([e[2].var_name for e in pet.in_edges(loop_cu_child.id, EdgeType.DATA)]) + set([e[2].var_name for e in in_edges(pet, loop_cu_child.id, EdgeType.DATA)]) ): if in_dep_var_name in ts.shared: # check if the found dependency occurs in the scope of the suggested task @@ -346,7 +350,7 @@ def __identify_atomic_or_critical_sections( break if parent_idx == child_idx: continue - if combinations[child_idx][0] in pet.direct_successors(combinations[parent_idx][-1]): + if combinations[child_idx][0] in direct_successors(pet, combinations[parent_idx][-1]): combinations[parent_idx] += combinations[child_idx] combinations.pop(child_idx) found_combination = True diff --git a/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py b/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py index 7a11c679a..7a7cf1bd6 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py @@ -12,6 +12,8 @@ from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX from discopop_explorer.classes.PEGraph.DummyNode import DummyNode from discopop_explorer.enums.MWType import MWType +from discopop_explorer.functions.PEGraph.queries.nodes import all_nodes +from discopop_explorer.functions.PEGraph.traversal.children import direct_children_or_called_nodes from discopop_explorer.utilities.PEGraphConstruction.parser import parse_inputs from discopop_explorer.classes.patterns.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.do_all_detector import run_detection as detect_do_all @@ -150,10 +152,10 @@ def run_detection( """ result: List[PatternInfo] = [] - for node in pet.all_nodes(): + for node in all_nodes(pet): if isinstance(node, DummyNode): continue - if pet.direct_children_or_called_nodes(node): + if direct_children_or_called_nodes(pet, node): detect_mw_types(pet, node) if node.mw_type == MWType.NONE: diff --git a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py index 0269f8a75..81ae22c58 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py @@ -23,6 +23,9 @@ from discopop_explorer.enums.MWType import MWType from discopop_explorer.enums.DepType import DepType from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.queries.edges import in_edges, out_edges +from discopop_explorer.functions.PEGraph.queries.nodes import all_nodes +from discopop_explorer.functions.PEGraph.traversal.children import direct_children_or_called_nodes from discopop_explorer.pattern_detectors.task_parallelism.classes import Task, TaskParallelismInfo from discopop_explorer.utils import depends @@ -106,7 +109,9 @@ def get_parent_of_type( last_node = cur_node visited.append(cur_node) tmp_list = [ - (s, t, e) for s, t, e in pet.in_edges(cur_node.id) if pet.node_at(s) not in visited and e.etype == edge_type + (s, t, e) + for s, t, e in in_edges(pet, cur_node.id) + if pet.node_at(s) not in visited and e.etype == edge_type ] for e in tmp_list: if pet.node_at(e[0]).type == parent_type: @@ -133,7 +138,7 @@ def get_cus_inside_function(pet: PEGraphX, function_cu: Node) -> List[Node]: if cur_cu not in result_list: result_list.append(cur_cu) # append children to queue - for e in pet.out_edges(cur_cu.id, [EdgeType.CHILD]): + for e in out_edges(pet, cur_cu.id, [EdgeType.CHILD]): queue.append(pet.node_at(e[1])) return result_list @@ -152,7 +157,7 @@ def check_reachability(pet: PEGraphX, target: Node, source: Node, edge_types: Li while len(queue) > 0: cur_node = queue.pop(0) visited.append(cur_node.id) - tmp_list = [(s, t, e) for s, t, e in pet.in_edges(cur_node.id) if s not in visited and e.etype in edge_types] + tmp_list = [(s, t, e) for s, t, e in in_edges(pet, cur_node.id) if s not in visited and e.etype in edge_types] for e in tmp_list: if pet.node_at(e[0]) == source: return True @@ -179,7 +184,7 @@ def get_predecessor_nodes(pet: PEGraphX, root: Node, visited_nodes: List[Node]) return result, visited_nodes in_succ_edges = [ (s, t, e) - for s, t, e in pet.in_edges(root.id) + for s, t, e in in_edges(pet, root.id) if e.etype == EdgeType.SUCCESSOR and pet.node_at(s) != root and pet.node_at(s) not in visited_nodes ] for e in in_succ_edges: @@ -266,7 +271,7 @@ def create_task_tree_helper(pet: PEGraphX, current: Node, root: Task, visited_fu else: visited_func.append(current) - for child in pet.direct_children_or_called_nodes(current): + for child in direct_children_or_called_nodes(pet, current): mw_type = child.mw_type if mw_type in [MWType.BARRIER, MWType.BARRIER_WORKER, MWType.WORKER]: @@ -534,13 +539,13 @@ def get_called_functions_recursively( """returns a recursively generated list of called functions, started at root.""" visited.append(root) called_functions: List[Union[FunctionNode, DummyNode]] = [] - for child in [pet.node_at(cuid) for cuid in [e[1] for e in pet.out_edges(root.id)]]: + for child in [pet.node_at(cuid) for cuid in [e[1] for e in out_edges(pet, root.id)]]: # check if type is Func or Dummy if isinstance(child, (FunctionNode, DummyNode)): # CU contains a function call # if Dummy, map to Func if isinstance(child, DummyNode): - for function_cu in pet.all_nodes(FunctionNode): + for function_cu in all_nodes(pet, FunctionNode): if child.name == function_cu.name: child = function_cu called_functions.append(cast(Union[FunctionNode, DummyNode], child)) @@ -577,7 +582,7 @@ def detect_mw_types(pet: PEGraphX, main_node: Node) -> None: """ # first insert all the direct children of main node in a queue to use it for the BFS - for node in pet.direct_children_or_called_nodes(main_node): + for node in direct_children_or_called_nodes(pet, main_node): # a child node can be set to NONE or ROOT due a former detectMWNode call where it was the mainNode if node.mw_type == MWType.NONE or node.mw_type == MWType.ROOT: node.mw_type = MWType.FORK @@ -592,7 +597,7 @@ def detect_mw_types(pet: PEGraphX, main_node: Node) -> None: # the other node # create the copy vector so that it only contains the other nodes - other_nodes = pet.direct_children_or_called_nodes(main_node) + other_nodes = direct_children_or_called_nodes(pet, main_node) other_nodes.remove(node) for other_node in other_nodes: @@ -606,7 +611,7 @@ def detect_mw_types(pet: PEGraphX, main_node: Node) -> None: # -> not detected in previous step, since other_node is only # dependent of a single CU raw_targets = [] - for s, t, d in pet.out_edges(other_node.id): + for s, t, d in out_edges(pet, other_node.id): if pet.node_at(t) == node: if d.dtype == DepType.RAW: raw_targets.append(t) @@ -622,13 +627,13 @@ def detect_mw_types(pet: PEGraphX, main_node: Node) -> None: # check for Barrier Worker pairs # if two barriers don't have any dependency to each other then they create a barrierWorker pair # so check every barrier pair that they don't have a dependency to each other -> barrierWorker - direct_subnodes = pet.direct_children_or_called_nodes(main_node) + direct_subnodes = direct_children_or_called_nodes(pet, main_node) for n1 in direct_subnodes: if n1.mw_type == MWType.BARRIER: for n2 in direct_subnodes: if n2.mw_type == MWType.BARRIER and n1 != n2: - if n2 in [pet.node_at(t) for s, t, d in pet.out_edges(n1.id)] or n2 in [ - pet.node_at(s) for s, t, d in pet.in_edges(n1.id) + if n2 in [pet.node_at(t) for s, t, d in out_edges(pet, n1.id)] or n2 in [ + pet.node_at(s) for s, t, d in in_edges(pet, n1.id) ]: break # so these two nodes are BarrierWorker, because there is no dependency between them diff --git a/discopop_explorer/plugins/pipeline.py b/discopop_explorer/plugins/pipeline.py index 421fd2ffd..e2ffaa7d1 100644 --- a/discopop_explorer/plugins/pipeline.py +++ b/discopop_explorer/plugins/pipeline.py @@ -14,6 +14,10 @@ from discopop_explorer.classes.PEGraph.Node import Node from discopop_explorer.aliases.LineID import LineID from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.properties.depends_ignore_readonly import depends_ignore_readonly +from discopop_explorer.functions.PEGraph.queries.edges import out_edges +from discopop_explorer.functions.PEGraph.queries.nodes import all_nodes +from discopop_explorer.functions.PEGraph.queries.subtree import subtree_of_type from discopop_explorer.utils import correlation_coefficient total = 0 @@ -26,7 +30,7 @@ def run_before(pet: PEGraphX) -> PEGraphX: def run_after(pet: PEGraphX) -> PEGraphX: - for node in pet.all_nodes(LoopNode): + for node in all_nodes(pet, LoopNode): check_pipeline(pet, node) print(f"Total: {total}") @@ -48,11 +52,11 @@ def check_pipeline(pet: PEGraphX, root: Node) -> None: global before global after - children_start_lines = [v.start_position() for v in pet.subtree_of_type(root, LoopNode)] + children_start_lines = [v.start_position() for v in subtree_of_type(pet, root, LoopNode)] loop_subnodes = [ pet.node_at(t) - for s, t, d in pet.out_edges(root.id, [EdgeType.CHILD, EdgeType.CALLSNODE]) + for s, t, d in out_edges(pet, root.id, [EdgeType.CHILD, EdgeType.CALLSNODE]) if is_pipeline_subnode(root, pet.node_at(t), children_start_lines) ] @@ -137,7 +141,7 @@ def get_matrix(pet: PEGraphX, root: Node, loop_subnodes: List[Node]) -> List[Lis for i in range(0, len(loop_subnodes)): res.append([]) for j in range(0, len(loop_subnodes)): - res[i].append(int(pet.depends_ignore_readonly(loop_subnodes[i], loop_subnodes[j], root))) + res[i].append(int(depends_ignore_readonly(pet, loop_subnodes[i], loop_subnodes[j], root))) return res diff --git a/discopop_explorer/utilities/general/generate_Data_CUInst.py b/discopop_explorer/utilities/general/generate_Data_CUInst.py index dbfbb38da..f997599b9 100644 --- a/discopop_explorer/utilities/general/generate_Data_CUInst.py +++ b/discopop_explorer/utilities/general/generate_Data_CUInst.py @@ -20,6 +20,9 @@ from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.DepType import DepType from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.queries.edges import in_edges, out_edges +from discopop_explorer.functions.PEGraph.queries.nodes import all_nodes +from discopop_explorer.functions.PEGraph.traversal.children import direct_children_or_called_nodes from discopop_explorer.utilities.PEGraphConstruction.parser import parse_inputs @@ -30,7 +33,7 @@ def __collect_children_ids(pet: PEGraphX, parent_id: NodeID, children_ids: List[ children_ids.append(parent_id) children_ids = list(set(children_ids)) # collect all of its children - for child_node in pet.direct_children_or_called_nodes(pet.node_at(parent_id)): + for child_node in direct_children_or_called_nodes(pet, pet.node_at(parent_id)): children_ids += __collect_children_ids(pet, child_node.id, children_ids) children_ids = list(set(children_ids)) return children_ids @@ -41,7 +44,7 @@ def __recursive_call_inside_loop(pet: PEGraphX, recursive_function_call: str) -> :param pet: PET Graph :param recursive_function_call: string representation of a recursive function call, extracted from cu-xml :return: True, if recursive call inside any loop body. False otherwise.""" - for tmp_cu in pet.all_nodes(LoopNode): + for tmp_cu in all_nodes(pet, LoopNode): if __line_contained_in_region( LineID(recursive_function_call.split(" ")[-1].replace(",", "")), tmp_cu.start_position(), @@ -56,7 +59,7 @@ def __recursive_function_called_multiple_times_inside_function(pet: PEGraphX, re :param pet: PET Graph :param recursive_function_call: string representation of a recursive function call, extracted from cu-xml :return: True, if multiple calls exists. False otherwise.""" - for tmp_func_cu in pet.all_nodes(FunctionNode): + for tmp_func_cu in all_nodes(pet, FunctionNode): # 1. get parent function of recursive function call if not __line_contained_in_region( LineID(recursive_function_call.split(" ")[-1].replace(",", "")), @@ -81,7 +84,7 @@ def __recursive_function_called_multiple_times_inside_function(pet: PEGraphX, re if cur_cu not in contained_cus: contained_cus.append(cur_cu) # append cur_cu children to queue - for child_edge in pet.out_edges(cur_cu.id, [EdgeType.CHILD, EdgeType.CALLSNODE]): + for child_edge in out_edges(pet, cur_cu.id, [EdgeType.CHILD, EdgeType.CALLSNODE]): child_cu = pet.node_at(child_edge[1]) if child_cu not in queue and child_cu not in contained_cus: queue.append(child_cu) @@ -114,7 +117,7 @@ def __output_dependencies_of_type( :param dep_type: type of dependency to be handled :param dep_identifier: identifier corresponding to the given dep_type (|RAW|, |WAR|, |WAW|) """ - for dep in pet.in_edges(child_id, EdgeType.DATA): + for dep in in_edges(pet, child_id, EdgeType.DATA): if dep[2].dtype is not dep_type: continue if dep[2].source_line is None or dep[2].var_name is None or dep[2].sink_line is None: @@ -172,7 +175,9 @@ def cu_instantiation_input_cpp(pet: PEGraphX, output_file: str) -> None: :param pet: PET Graph :param output_file: Path to storage location of generated Data_CUInst.txt""" with open(output_file, "w+") as data_cu_inst_file: - for node in pet.all_nodes(): + for node in all_nodes( + pet, + ): __search_recursive_calls(pet, data_cu_inst_file, node) diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index 88c6a5373..7927ed7ef 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -12,6 +12,17 @@ import numpy as np import warnings +from discopop_explorer.functions.PEGraph.properties.is_loop_index import is_loop_index +from discopop_explorer.functions.PEGraph.properties.is_reduction_var_by_name import is_reduction_var_by_name +from discopop_explorer.functions.PEGraph.queries.edges import in_edges, out_edges +from discopop_explorer.functions.PEGraph.queries.reductions import get_reduction_sign +from discopop_explorer.functions.PEGraph.queries.subtree import get_left_right_subtree, subtree_of_type +from discopop_explorer.functions.PEGraph.queries.variables import get_undefined_variables_inside_loop, get_variables +from discopop_explorer.functions.PEGraph.traversal.children import ( + direct_children_or_called_nodes, + direct_children_or_called_nodes_of_type, +) +from discopop_explorer.functions.PEGraph.traversal.parent import get_parent_function from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType from discopop_library.HostpotLoader.HotspotType import HotspotType @@ -64,7 +75,7 @@ def find_subnodes(pet: PEGraphX, node: Node, criteria: EdgeType) -> List[Node]: :param criteria: EdgeType, type of edges to traverse :return: list of children nodes """ - return [pet.node_at(t) for s, t, d in pet.out_edges(node.id) if d.etype == criteria] + return [pet.node_at(t) for s, t, d in out_edges(pet, node.id) if d.etype == criteria] def depends(pet: PEGraphX, source: Node, target: Node) -> bool: @@ -77,12 +88,12 @@ def depends(pet: PEGraphX, source: Node, target: Node) -> bool: """ if source == target: return False - target_nodes = pet.subtree_of_type(target) + target_nodes = subtree_of_type(pet, target) - for node in pet.subtree_of_type(source, CUNode): + for node in subtree_of_type(pet, source, CUNode): for target in [ pet.node_at(target_id) - for source_id, target_id, dependence in pet.out_edges(node.id, EdgeType.DATA) + for source_id, target_id, dependence in out_edges(pet, node.id, EdgeType.DATA) if dependence.dtype == DepType.RAW ]: if target in target_nodes: @@ -98,8 +109,8 @@ def is_loop_index2(pet: PEGraphX, root_loop: Node, var_name: str) -> bool: :param var_name: name of the variable :return: true if variable is index of the loop """ - loops_start_lines = [v.start_position() for v in pet.subtree_of_type(root_loop, LoopNode)] - return pet.is_loop_index(var_name, loops_start_lines, pet.subtree_of_type(root_loop, CUNode)) + loops_start_lines = [v.start_position() for v in subtree_of_type(pet, root_loop, LoopNode)] + return is_loop_index(pet, var_name, loops_start_lines, subtree_of_type(pet, root_loop, CUNode)) # NOTE: left old code as it may become relevant again in the near future @@ -126,7 +137,7 @@ def calculate_workload(pet: PEGraphX, node: Node, ignore_function_calls_and_cach # note: recursive function calls are counted as a single instruction res += cast(CUNode, node).instructions_count if not ignore_function_calls_and_cached_values: - for calls_edge in pet.out_edges(cast(CUNode, node).id, EdgeType.CALLSNODE): + for calls_edge in out_edges(pet, cast(CUNode, node).id, EdgeType.CALLSNODE): # add costs of the called function res += calculate_workload( pet, @@ -246,7 +257,7 @@ def __get_dep_of_type( """ return [ e - for e in (pet.in_edges(node.id, EdgeType.DATA) if reversed else pet.out_edges(node.id, EdgeType.DATA)) + for e in (in_edges(pet, node.id, EdgeType.DATA) if reversed else out_edges(pet, node.id, EdgeType.DATA)) if e[2].dtype == dep_type ] @@ -327,7 +338,7 @@ def is_func_arg(pet: PEGraphX, var: str, node: Node) -> bool: return False if "." not in var: return False - parents = [pet.node_at(edge[0]) for edge in pet.in_edges(node.id, EdgeType.CHILD)] + parents = [pet.node_at(edge[0]) for edge in in_edges(pet, node.id, EdgeType.CHILD)] # add current node to parents, if it is of type FUNC if isinstance(node, FunctionNode): parents.append(node) @@ -602,14 +613,14 @@ def get_child_loops(pet: PEGraphX, node: Node) -> Tuple[List[Node], List[Node]]: do_all: List[Node] = [] reduction: List[Node] = [] - for loop_child in pet.subtree_of_type(node, LoopNode): + for loop_child in subtree_of_type(pet, node, LoopNode): if loop_child.do_all: do_all.append(loop_child) elif loop_child.reduction: reduction.append(loop_child) - for func_child in pet.direct_children_or_called_nodes_of_type(node, FunctionNode): - for child in pet.direct_children_or_called_nodes_of_type(func_child, CUNode): + for func_child in direct_children_or_called_nodes_of_type(pet, node, FunctionNode): + for child in direct_children_or_called_nodes_of_type(pet, func_child, CUNode): if child.do_all: do_all.append(child) elif child.reduction: @@ -621,8 +632,8 @@ def get_child_loops(pet: PEGraphX, node: Node) -> Tuple[List[Node], List[Node]]: def get_initialized_memory_regions_in(pet: PEGraphX, cu_nodes: List[CUNode]) -> Dict[Variable, Set[MemoryRegion]]: initialized_memory_regions: Dict[Variable, Set[MemoryRegion]] = dict() for cu in cu_nodes: - parent_function = pet.get_parent_function(cu) - for s, t, d in pet.out_edges(cu.id, EdgeType.DATA): + parent_function = get_parent_function(pet, cu) + for s, t, d in out_edges(pet, cu.id, EdgeType.DATA): if d.dtype == DepType.INIT and d.memory_region is not None: # get variable object from cu for var in cu.global_vars + cu.local_vars: @@ -661,9 +672,9 @@ def classify_loop_variables( last_private = [] shared = [] reduction = [] - lst = pet.get_left_right_subtree(loop, False) - rst = pet.get_left_right_subtree(loop, True) - sub: List[CUNode] = pet.subtree_of_type(loop, CUNode) + lst = get_left_right_subtree(pet, loop, False) + rst = get_left_right_subtree(pet, loop, True) + sub: List[CUNode] = subtree_of_type(pet, loop, CUNode) raw = set() war = set() @@ -676,12 +687,12 @@ def classify_loop_variables( waw.update(__get_dep_of_type(pet, sub_node, DepType.WAW, False)) rev_raw.update(__get_dep_of_type(pet, sub_node, DepType.RAW, True)) - vars = pet.get_undefined_variables_inside_loop(loop) + vars = get_undefined_variables_inside_loop(pet, loop) # only consider memory regions which are know at the current code location. # ignore memory regions which stem from called functions. - left_subtree_without_called_nodes = pet.get_left_right_subtree(loop, False, ignore_called_nodes=True) - prior_known_vars = pet.get_variables(left_subtree_without_called_nodes) + left_subtree_without_called_nodes = get_left_right_subtree(pet, loop, False, ignore_called_nodes=True) + prior_known_vars = get_variables(pet, left_subtree_without_called_nodes) prior_known_mem_regs = set() for pkv in prior_known_vars: prior_known_mem_regs.update(prior_known_vars[pkv]) @@ -717,8 +728,8 @@ def classify_loop_variables( last_private.append(var) else: private.append(var) - elif loop.reduction and pet.is_reduction_var(loop.start_position(), var.name): - var.operation = pet.get_reduction_sign(loop.start_position(), var.name) + elif loop.reduction and is_reduction_var_by_name(pet, loop.start_position(), var.name): + var.operation = get_reduction_sign(pet, loop.start_position(), var.name) reduction.append(var) elif ( is_written_in_subtree(mem_reg_subset, raw, waw, lst) @@ -935,15 +946,15 @@ def classify_task_vars( depend_in_out: List[Tuple[Variable, Set[MemoryRegion]]] = [] reduction_var_names: List[str] = [] - left_sub_tree = pet.get_left_right_subtree(task, False) + left_sub_tree = get_left_right_subtree(pet, task, False) - right_sub_tree = pet.get_left_right_subtree(task, True) - subtree = pet.subtree_of_type(task, CUNode) - t_loop = pet.subtree_of_type(task, LoopNode) + right_sub_tree = get_left_right_subtree(pet, task, True) + subtree = subtree_of_type(pet, task, CUNode) + t_loop = subtree_of_type(pet, task, LoopNode) vars: Dict[Variable, Set[MemoryRegion]] = dict() if isinstance(task, FunctionNode): - tmp = pet.get_variables(subtree) + tmp = get_variables(pet, subtree) vars_strings = [] for v in task.args: vars_strings.append(v.name) @@ -960,7 +971,7 @@ def classify_task_vars( if name in vars_strings: vars[v] = tmp[v] else: - vars = pet.get_variables(subtree) + vars = get_variables(pet, subtree) raw_deps_on = set() # set war_deps_on = set() @@ -994,14 +1005,14 @@ def classify_task_vars( loop_nodes.append(task) loops_start_lines = [n.start_position() for n in loop_nodes] - loop_children = [c for n in loop_nodes for c in pet.direct_children_or_called_nodes(n)] + loop_children = [c for n in loop_nodes for c in direct_children_or_called_nodes(pet, n)] for var in vars: var_is_loop_index = False # get RAW dependencies for var tmp_deps = [dep for dep in raw_deps_on if dep[2].memory_region in vars[var]] for edge in tmp_deps: - if pet.is_loop_index(edge[2].var_name, loops_start_lines, loop_children): + if is_loop_index(pet, edge[2].var_name, loops_start_lines, loop_children): var_is_loop_index = True break if var_is_loop_index: @@ -1051,8 +1062,8 @@ def classify_task_vars( shared.append((var, vars[var])) # use known variables to reconstruct the correct variable names from the classified memory regions - left_subtree_without_called_nodes = pet.get_left_right_subtree(task, False, ignore_called_nodes=True) - prior_known_vars = pet.get_variables(left_subtree_without_called_nodes) + left_subtree_without_called_nodes = get_left_right_subtree(pet, task, False, ignore_called_nodes=True) + prior_known_vars = get_variables(pet, left_subtree_without_called_nodes) return ( sorted(__apply_dealiasing(first_private, prior_known_vars)), @@ -1095,12 +1106,12 @@ def __is_written_prior_to_task(pet: PEGraphX, var: Variable, task: Node) -> bool predecessors.append(current) queue += [ pet.node_at(edge[0]) - for edge in pet.in_edges(current.id, EdgeType.SUCCESSOR) + for edge in in_edges(pet, current.id, EdgeType.SUCCESSOR) if pet.node_at(edge[0]) not in visited ] # check if raw-dependency on var to any predecessor exists) - for out_dep in pet.out_edges(task.id, EdgeType.DATA): + for out_dep in out_edges(pet, task.id, EdgeType.DATA): if out_dep[2].dtype != DepType.RAW: continue # check if out_dep.source in predecessors From 01bdf19ba62cb4bf7f4c25a024063a08b4b0cb3f Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Thu, 1 Aug 2024 15:41:09 +0200 Subject: [PATCH 075/105] fix: missing replacements of all_nodes calls --- .../DataTransfers/DataTransfers.py | 5 ++-- .../PETParser/DataAccesses/FromCUs.py | 11 ++++--- .../discopop_optimizer/PETParser/PETParser.py | 29 ++++++++++--------- .../UpdateOptimization/AddRangesToUpdates.py | 16 ++++++---- .../classes/nodes/Workload.py | 4 ++- .../optimization/validation.py | 5 ++-- 6 files changed, 42 insertions(+), 28 deletions(-) diff --git a/discopop_library/discopop_optimizer/DataTransfers/DataTransfers.py b/discopop_library/discopop_optimizer/DataTransfers/DataTransfers.py index b2bd59a58..b0f5e88d1 100644 --- a/discopop_library/discopop_optimizer/DataTransfers/DataTransfers.py +++ b/discopop_library/discopop_optimizer/DataTransfers/DataTransfers.py @@ -11,6 +11,7 @@ from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.queries.edges import out_edges from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.context.ContextObject import ContextObject @@ -156,8 +157,8 @@ def get_path_context_iterative( node_data = data_at(graph, node) if node_data.original_cu_id is None: continue - for out_dep_edge in experiment.detection_result.pet.out_edges( - node_data.original_cu_id, etype=EdgeType.DATA + for out_dep_edge in out_edges( + experiment.detection_result.pet, node_data.original_cu_id, etype=EdgeType.DATA ): target = out_dep_edge[1] if target in cu_nodes_in_function: diff --git a/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py b/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py index 3520f8011..e557bc9c0 100644 --- a/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py +++ b/discopop_library/discopop_optimizer/PETParser/DataAccesses/FromCUs.py @@ -13,6 +13,9 @@ from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.DepType import DepType from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.queries.edges import in_edges, out_edges +from discopop_explorer.functions.PEGraph.queries.subtree import subtree_of_type +from discopop_explorer.functions.PEGraph.traversal.parent import get_parent_function from discopop_library.discopop_optimizer.classes.types.DataAccessType import ( WriteDataAccess, ReadDataAccess, @@ -31,11 +34,11 @@ def get_next_free_unique_write_id() -> int: def get_data_accesses_for_cu(pet: PEGraphX, cu_id: NodeID) -> Tuple[Set[WriteDataAccess], Set[ReadDataAccess]]: """Calculates and returns the sets of accessed memory regions for the given cu node. The first element contains write accesses, the second element contains read accesses.""" - parent_function = pet.get_parent_function(pet.node_at(cu_id)) - subtree = pet.subtree_of_type(parent_function, CUNode) + parent_function = get_parent_function(pet, pet.node_at(cu_id)) + subtree = subtree_of_type(pet, parent_function, CUNode) - in_dep_edges = pet.in_edges(cu_id, EdgeType.DATA) - out_dep_edges = pet.out_edges(cu_id, EdgeType.DATA) + in_dep_edges = in_edges(pet, cu_id, EdgeType.DATA) + out_dep_edges = out_edges(pet, cu_id, EdgeType.DATA) written_memory_regions = [ WriteDataAccess(MemoryRegion(cast(str, d.memory_region)), get_next_free_unique_write_id(), d.var_name) diff --git a/discopop_library/discopop_optimizer/PETParser/PETParser.py b/discopop_library/discopop_optimizer/PETParser/PETParser.py index af27178e9..8221d6f50 100644 --- a/discopop_library/discopop_optimizer/PETParser/PETParser.py +++ b/discopop_library/discopop_optimizer/PETParser/PETParser.py @@ -25,6 +25,9 @@ from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.queries.edges import in_edges, out_edges +from discopop_explorer.functions.PEGraph.queries.nodes import all_nodes +from discopop_explorer.functions.PEGraph.queries.subtree import subtree_of_type from discopop_explorer.utils import calculate_workload from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType from discopop_library.discopop_optimizer.PETParser.DataAccesses.FromCUs import ( @@ -194,8 +197,8 @@ def __add_calling_edges(self) -> None: # get functions called by the node if node_data.original_cu_id is None: raise ValueError("Node: " + str(node) + " has no original_cu_id") - for out_call_edge in self.experiment.detection_result.pet.out_edges( - node_data.original_cu_id, etype=EdgeType.CALLSNODE + for out_call_edge in out_edges( + self.experiment.detection_result.pet, node_data.original_cu_id, etype=EdgeType.CALLSNODE ): # create a call edge to the function for function in all_function_nodes: @@ -1056,8 +1059,8 @@ def __parse_branched_sections(self) -> None: To make this possible, Context Snapshot, Restore and Merge points are added to allow a synchronization 'between' the different branches""" visited_nodes: Set[int] = set() - for idx, function_node in enumerate(self.pet.all_nodes(FunctionNode)): - print("parsing ", function_node.name, idx, "/", len(self.pet.all_nodes(FunctionNode))) + for idx, function_node in enumerate(all_nodes(self.pet, FunctionNode)): + print("parsing ", function_node.name, idx, "/", len(all_nodes(self.pet, FunctionNode))) _, _ = self.__parse_raw_node(self.cu_id_to_graph_node_id[function_node.id], visited_nodes) # remove visited nodes, since duplicates exist now @@ -1181,7 +1184,7 @@ def __parse_branching_point( def __add_cu_nodes(self) -> None: """adds Workload nodes which represent the CU Nodes to the graph. The added nodes will not be connected in any way.""" - for cu_node in self.pet.all_nodes(CUNode): + for cu_node in all_nodes(self.pet, CUNode): # create new node for CU new_node_id = self.get_new_node_id() self.cu_id_to_graph_node_id[cu_node.id] = new_node_id @@ -1210,9 +1213,9 @@ def __add_cu_nodes(self) -> None: def __add_loop_nodes(self) -> None: """adds Loop Nodes to the graph. connects contained nodes using Children edges""" - for loop_node in self.pet.all_nodes(LoopNode): + for loop_node in all_nodes(self.pet, LoopNode): # calculate metadata - loop_subtree = self.pet.subtree_of_type(loop_node, CUNode) + loop_subtree = subtree_of_type(self.pet, loop_node, CUNode) # get iteration count for loop if loop_node.loop_data is not None: @@ -1251,7 +1254,7 @@ def __add_loop_nodes(self) -> None: add_child_edge(self.graph, new_node_id, self.cu_id_to_graph_node_id[entry_node_cu_id]) # redirect edges from outside the loop to the entry node to the Loop node - for s, t, d in self.pet.in_edges(entry_node_cu_id, EdgeType.SUCCESSOR): + for s, t, d in in_edges(self.pet, entry_node_cu_id, EdgeType.SUCCESSOR): if self.pet.node_at(s) not in loop_subtree: try: redirect_edge( @@ -1266,7 +1269,7 @@ def __add_loop_nodes(self) -> None: print("ignoring redirect of edge due to KeyError: ", ke) # redirect edges to the outside of the loop - for s, t, d in self.pet.out_edges(entry_node_cu_id, EdgeType.SUCCESSOR): + for s, t, d in out_edges(self.pet, entry_node_cu_id, EdgeType.SUCCESSOR): if self.pet.node_at(t) not in loop_subtree: redirect_edge( self.graph, @@ -1283,7 +1286,7 @@ def __add_loop_nodes(self) -> None: self.graph.add_node(copied_entry_node_id, data=entry_node_data) # redirect edges from inside the loop to the copy of the entry node - for s, t, d in self.pet.in_edges(entry_node_cu_id, EdgeType.SUCCESSOR): + for s, t, d in in_edges(self.pet, entry_node_cu_id, EdgeType.SUCCESSOR): if self.pet.node_at(s) in loop_subtree: redirect_edge( self.graph, @@ -1299,7 +1302,7 @@ def __add_loop_nodes(self) -> None: def __add_functions(self) -> None: """parse function nodes in the PET graph. Results in the creation of a forest of function graphs.""" - for function_node in self.pet.all_nodes(FunctionNode): + for function_node in all_nodes(self.pet, FunctionNode): # create function root node and register it in the graph new_node_id = self.get_new_node_id() self.graph.add_node( @@ -1321,8 +1324,8 @@ def __add_functions(self) -> None: self.cu_id_to_graph_node_id[function_node.id] = new_node_id def __add_pet_successor_edges(self) -> None: - for cu_node in self.pet.all_nodes(CUNode): - for successor_cu_id in [t for s, t, d in self.pet.out_edges(cu_node.id, EdgeType.SUCCESSOR)]: + for cu_node in all_nodes(self.pet, CUNode): + for successor_cu_id in [t for s, t, d in out_edges(self.pet, cu_node.id, EdgeType.SUCCESSOR)]: add_successor_edge( self.graph, self.cu_id_to_graph_node_id[cu_node.id], diff --git a/discopop_library/discopop_optimizer/UpdateOptimization/AddRangesToUpdates.py b/discopop_library/discopop_optimizer/UpdateOptimization/AddRangesToUpdates.py index 5a2b178e8..68d7e2a5a 100644 --- a/discopop_library/discopop_optimizer/UpdateOptimization/AddRangesToUpdates.py +++ b/discopop_library/discopop_optimizer/UpdateOptimization/AddRangesToUpdates.py @@ -10,6 +10,7 @@ from discopop_explorer.aliases.MemoryRegion import MemoryRegion from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.classes.variable import Variable +from discopop_explorer.functions.PEGraph.queries.variables import get_variables from discopop_library.discopop_optimizer.OptimizerArguments import OptimizerArguments from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.utilities.simple_utilities import data_at @@ -26,8 +27,9 @@ def add_ranges_to_updates( candidate_variables: Dict[Variable, Set[MemoryRegion]] = dict() # collect known variables from source - variables = experiment.detection_result.pet.get_variables( - [experiment.detection_result.pet.node_at(cast(NodeID, update.source_cu_id))] + variables = get_variables( + experiment.detection_result.pet, + [experiment.detection_result.pet.node_at(cast(NodeID, update.source_cu_id))], ) for v in variables: @@ -37,8 +39,9 @@ def add_ranges_to_updates( # collect known variabled from target - variables = experiment.detection_result.pet.get_variables( - [experiment.detection_result.pet.node_at(cast(NodeID, update.target_cu_id))] + variables = get_variables( + experiment.detection_result.pet, + [experiment.detection_result.pet.node_at(cast(NodeID, update.target_cu_id))], ) for v in variables: @@ -48,12 +51,13 @@ def add_ranges_to_updates( if update.originated_from_node is not None: # collect known variabled from originated_from_node - variables = experiment.detection_result.pet.get_variables( + variables = get_variables( + experiment.detection_result.pet, [ experiment.detection_result.pet.node_at( cast(NodeID, data_at(experiment.optimization_graph, update.originated_from_node).original_cu_id) ) - ] + ], ) for v in variables: if v not in candidate_variables: diff --git a/discopop_library/discopop_optimizer/classes/nodes/Workload.py b/discopop_library/discopop_optimizer/classes/nodes/Workload.py index 22b1dc207..5a155e4a9 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/Workload.py +++ b/discopop_library/discopop_optimizer/classes/nodes/Workload.py @@ -12,6 +12,7 @@ from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.queries.edges import out_edges from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel from typing import TYPE_CHECKING @@ -121,7 +122,8 @@ def __get_costs_of_function_call( # get CUIDs of called functions if self.original_cu_id is not None: called_cu_ids: List[str] = [ - str(t) for s, t, d in experiment.detection_result.pet.out_edges(self.original_cu_id, EdgeType.CALLSNODE) + str(t) + for s, t, d in out_edges(experiment.detection_result.pet, self.original_cu_id, EdgeType.CALLSNODE) ] # filter for called FunctionRoots called_function_nodes = [fr for fr in all_function_nodes if str(fr.original_cu_id) in called_cu_ids] diff --git a/discopop_library/discopop_optimizer/optimization/validation.py b/discopop_library/discopop_optimizer/optimization/validation.py index 66e61f879..3e4a6ca0a 100644 --- a/discopop_library/discopop_optimizer/optimization/validation.py +++ b/discopop_library/discopop_optimizer/optimization/validation.py @@ -9,6 +9,7 @@ from typing import List, cast, Set from discopop_explorer.aliases.NodeID import NodeID from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.queries.edges import out_edges from discopop_library.discopop_optimizer.OptimizerArguments import OptimizerArguments from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.nodes.FunctionRoot import FunctionRoot @@ -109,8 +110,8 @@ def __nested_parallelism_found(experiment: Experiment, configuration: List[int], # add called functions called_cu_ids: List[str] = [ str(t) - for s, t, d in experiment.detection_result.pet.out_edges( - cast(NodeID, current_node.original_cu_id), EdgeType.CALLSNODE + for s, t, d in out_edges( + experiment.detection_result.pet, cast(NodeID, current_node.original_cu_id), EdgeType.CALLSNODE ) ] # filter for called FunctionRoots From aab879a61599e915be73d6d4b506a750f612fef4 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Thu, 1 Aug 2024 17:02:15 +0200 Subject: [PATCH 076/105] fix: missing replacements of all_nodes calls --- discopop_library/EmpiricalAutotuning/Autotuner.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/discopop_library/EmpiricalAutotuning/Autotuner.py b/discopop_library/EmpiricalAutotuning/Autotuner.py index 96e738dd8..f63078cb3 100644 --- a/discopop_library/EmpiricalAutotuning/Autotuner.py +++ b/discopop_library/EmpiricalAutotuning/Autotuner.py @@ -12,6 +12,7 @@ import jsonpickle # type: ignore from discopop_explorer.classes.PEGraph.LoopNode import LoopNode +from discopop_explorer.functions.PEGraph.queries.nodes import all_nodes from discopop_library.EmpiricalAutotuning.ArgumentClasses import AutotunerArguments from discopop_library.EmpiricalAutotuning.Classes.CodeConfiguration import CodeConfiguration from discopop_library.EmpiricalAutotuning.Classes.ExecutionResult import ExecutionResult @@ -87,7 +88,7 @@ def run(arguments: AutotunerArguments) -> None: else: # no hotspot information was found # get loop tuples from detection result - loop_nodes = detection_result.pet.all_nodes(type=LoopNode) + loop_nodes = all_nodes(detection_result.pet, type=LoopNode) loop_tuples = [(l.file_id, l.start_line, HotspotNodeType.LOOP, "", 0.0) for l in loop_nodes] sorted_loop_tuples = sorted(loop_tuples, key=lambda x: x[4], reverse=True) From 6d1c9e7b49d27475577a3218dc830e2b3b27c6b0 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Thu, 1 Aug 2024 17:07:52 +0200 Subject: [PATCH 077/105] chore: update requirements.txt --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index f20eea8a8..37dd1400d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,7 +11,7 @@ about-time==4.2.1 alive-progress==3.1.4 appdirs==1.4.4 -black==24.3.0 +black==24.4.2 click==8.1.7 contextlib2==21.6.0 contourpy==1.1.0 From 1b58bb4597eea90e8e57840e4189538d666fa037 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Fri, 2 Aug 2024 08:21:16 +0200 Subject: [PATCH 078/105] chore: formatting --- discopop_explorer/classes/PEGraph/Node.py | 6 ++--- .../functions/PEGraph/queries/nodes.py | 6 ++--- .../functions/PEGraph/queries/subtree.py | 12 ++++------ .../CombinedGPURegions.py | 24 +++++++++---------- .../combined_gpu_patterns/prepare_metadata.py | 7 +++--- discopop_explorer/utils.py | 10 +++++++- 6 files changed, 34 insertions(+), 31 deletions(-) diff --git a/discopop_explorer/classes/PEGraph/Node.py b/discopop_explorer/classes/PEGraph/Node.py index 1941e6c76..34aa56487 100644 --- a/discopop_explorer/classes/PEGraph/Node.py +++ b/discopop_explorer/classes/PEGraph/Node.py @@ -27,9 +27,9 @@ class Node: end_line: int type: NodeType name: str - parent_function_id: Optional[ - NodeID - ] = None # metadata to speedup some calculations (TODO FunctionNodes have themselves as parent) + parent_function_id: Optional[NodeID] = ( + None # metadata to speedup some calculations (TODO FunctionNodes have themselves as parent) + ) workload: Optional[int] = None # properties of CU Nodes diff --git a/discopop_explorer/functions/PEGraph/queries/nodes.py b/discopop_explorer/functions/PEGraph/queries/nodes.py index 26bd6cf50..ef191302b 100644 --- a/discopop_explorer/functions/PEGraph/queries/nodes.py +++ b/discopop_explorer/functions/PEGraph/queries/nodes.py @@ -16,13 +16,11 @@ @overload -def all_nodes(pet: PEGraphX) -> List[Node]: - ... +def all_nodes(pet: PEGraphX) -> List[Node]: ... @overload -def all_nodes(pet: PEGraphX, type: Union[Type[NodeT], Tuple[Type[NodeT], ...]]) -> List[NodeT]: - ... +def all_nodes(pet: PEGraphX, type: Union[Type[NodeT], Tuple[Type[NodeT], ...]]) -> List[NodeT]: ... def all_nodes(pet: PEGraphX, type: Any = Node) -> List[NodeT]: diff --git a/discopop_explorer/functions/PEGraph/queries/subtree.py b/discopop_explorer/functions/PEGraph/queries/subtree.py index 87468370c..692255097 100644 --- a/discopop_explorer/functions/PEGraph/queries/subtree.py +++ b/discopop_explorer/functions/PEGraph/queries/subtree.py @@ -60,13 +60,11 @@ def get_left_right_subtree( @overload -def subtree_of_type(pet: PEGraphX, root: Node) -> List[Node]: - ... +def subtree_of_type(pet: PEGraphX, root: Node) -> List[Node]: ... @overload -def subtree_of_type(pet: PEGraphX, root: Node, type: Union[Type[NodeT], Tuple[Type[NodeT], ...]]) -> List[NodeT]: - ... +def subtree_of_type(pet: PEGraphX, root: Node, type: Union[Type[NodeT], Tuple[Type[NodeT], ...]]) -> List[NodeT]: ... def subtree_of_type(pet: PEGraphX, root: Node, type: Any = Node) -> List[NodeT]: @@ -80,15 +78,13 @@ def subtree_of_type(pet: PEGraphX, root: Node, type: Any = Node) -> List[NodeT]: @overload -def subtree_of_type_rec(pet: PEGraphX, root: Node, visited: Set[Node]) -> List[Node]: - ... +def subtree_of_type_rec(pet: PEGraphX, root: Node, visited: Set[Node]) -> List[Node]: ... @overload def subtree_of_type_rec( pet: PEGraphX, root: Node, visited: Set[Node], type: Union[Type[NodeT], Tuple[Type[NodeT], ...]] -) -> List[NodeT]: - ... +) -> List[NodeT]: ... def subtree_of_type_rec(pet: PEGraphX, root: Node, visited: Set[Node], type: Any = Node) -> List[NodeT]: diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py index f8f432278..211e40fc0 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py @@ -135,9 +135,9 @@ def __init__(self, pet: PEGraphX, contained_regions: List[GPURegionInfo], projec ) = get_written_and_read_memory_regions_by_cu(self.contained_regions, pet) # get memory region and variable associations for each CU - cu_and_variable_to_memory_regions: Dict[ - NodeID, Dict[VarName, Set[MemoryRegion]] - ] = get_cu_and_varname_to_memory_regions(self.contained_regions, pet, written_memory_regions_by_cu) + cu_and_variable_to_memory_regions: Dict[NodeID, Dict[VarName, Set[MemoryRegion]]] = ( + get_cu_and_varname_to_memory_regions(self.contained_regions, pet, written_memory_regions_by_cu) + ) print("WRITTEN MEMORY REGIONS BY CU: ", file=sys.stderr) print(written_memory_regions_by_cu, file=sys.stderr) @@ -148,9 +148,9 @@ def __init__(self, pet: PEGraphX, contained_regions: List[GPURegionInfo], projec print(file=sys.stderr) # get memory regions to cus and variables names - memory_regions_to_cus_and_variables: Dict[ - MemoryRegion, Dict[NodeID, Set[VarName]] - ] = get_memory_region_to_cu_and_variables_dict(cu_and_variable_to_memory_regions) + memory_regions_to_cus_and_variables: Dict[MemoryRegion, Dict[NodeID, Set[VarName]]] = ( + get_memory_region_to_cu_and_variables_dict(cu_and_variable_to_memory_regions) + ) print("MEMORY REGIONS TO CUS AND VARIABLES:", file=sys.stderr) print(memory_regions_to_cus_and_variables, file=sys.stderr) print(file=sys.stderr) @@ -162,9 +162,9 @@ def __init__(self, pet: PEGraphX, contained_regions: List[GPURegionInfo], projec print(file=sys.stderr) # extend device liveness with memory regions - device_liveness_plus_memory_regions: Dict[ - VarName, List[Tuple[NodeID, Set[MemoryRegion]]] - ] = add_memory_regions_to_device_liveness(live_device_variables, cu_and_variable_to_memory_regions) + device_liveness_plus_memory_regions: Dict[VarName, List[Tuple[NodeID, Set[MemoryRegion]]]] = ( + add_memory_regions_to_device_liveness(live_device_variables, cu_and_variable_to_memory_regions) + ) # ### STEP 2.2: CALCULATE LIVE DATA BY PROPAGATING MEMORY REGIONS AND EXTENDING LIFESPAN @@ -264,9 +264,9 @@ def __init__(self, pet: PEGraphX, contained_regions: List[GPURegionInfo], projec # ### STEP 5: CONVERT MEMORY REGIONS IN UPDATES TO VARIABLE NAMES # propagate memory region to variable name associations within function body - memory_regions_to_functions_and_variables: Dict[ - MemoryRegion, Dict[NodeID, Set[VarName]] - ] = propagate_variable_name_associations(pet, memory_regions_to_cus_and_variables) + memory_regions_to_functions_and_variables: Dict[MemoryRegion, Dict[NodeID, Set[VarName]]] = ( + propagate_variable_name_associations(pet, memory_regions_to_cus_and_variables) + ) print("MEMORY REGIONS TO FUNCTIONS AND VARIABLES:", file=sys.stderr) print(memory_regions_to_functions_and_variables, file=sys.stderr) print(file=sys.stderr) diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/prepare_metadata.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/prepare_metadata.py index 3f5144d71..5dfceba56 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/prepare_metadata.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/prepare_metadata.py @@ -14,9 +14,10 @@ from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Dependency import Dependency -def get_dependencies_as_metadata( - pet: PEGraphX, all_dependencies: Set[Dependency] -) -> Tuple[List[Tuple[VarName, NodeID, str]], List[Tuple[VarName, NodeID, str]],]: +def get_dependencies_as_metadata(pet: PEGraphX, all_dependencies: Set[Dependency]) -> Tuple[ + List[Tuple[VarName, NodeID, str]], + List[Tuple[VarName, NodeID, str]], +]: in_deps_metadata: Set[Tuple[VarName, NodeID, str]] = set() out_deps_metadata: Set[Tuple[VarName, NodeID, str]] = set() diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index 7927ed7ef..89d4a14b9 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -927,7 +927,15 @@ def classify_task_vars( in_deps: List[Tuple[NodeID, NodeID, Dependency]], out_deps: List[Tuple[NodeID, NodeID, Dependency]], used_in_task_parallelism_detection: bool = False, -) -> Tuple[List[Variable], List[Variable], List[Variable], List[Variable], List[Variable], List[Variable], List[str],]: +) -> Tuple[ + List[Variable], + List[Variable], + List[Variable], + List[Variable], + List[Variable], + List[Variable], + List[str], +]: """Classify task variables :param pet: CU graph From 1f056412ba3b3f2534ca2003561484b469b7a4c1 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Fri, 2 Aug 2024 08:24:37 +0200 Subject: [PATCH 079/105] chore: formatting --- .../Microbench/ExtrapInterpolatedMicrobench.py | 5 ++++- .../Microbench/MixedMicrobench.py | 15 ++++++++++++--- .../Microbench/PureDataMicrobench.py | 18 +++++++++++------- .../gui/presentation/OptionTable.py | 12 ++++++------ 4 files changed, 33 insertions(+), 17 deletions(-) diff --git a/discopop_library/discopop_optimizer/Microbench/ExtrapInterpolatedMicrobench.py b/discopop_library/discopop_optimizer/Microbench/ExtrapInterpolatedMicrobench.py index 00ee6e764..fbd72cb70 100644 --- a/discopop_library/discopop_optimizer/Microbench/ExtrapInterpolatedMicrobench.py +++ b/discopop_library/discopop_optimizer/Microbench/ExtrapInterpolatedMicrobench.py @@ -77,7 +77,10 @@ def getFunctionSympy( def getMeasurements( self, - ) -> Dict[MicrobenchType, Dict[MicrobenchDimension, Dict[MicrobenchCoordinate, List[float]]],]: + ) -> Dict[ + MicrobenchType, + Dict[MicrobenchDimension, Dict[MicrobenchCoordinate, List[float]]], + ]: raise NotImplementedError("TODO") # TODO def toJSON(self) -> str: diff --git a/discopop_library/discopop_optimizer/Microbench/MixedMicrobench.py b/discopop_library/discopop_optimizer/Microbench/MixedMicrobench.py index fc833807b..ec7c95b65 100644 --- a/discopop_library/discopop_optimizer/Microbench/MixedMicrobench.py +++ b/discopop_library/discopop_optimizer/Microbench/MixedMicrobench.py @@ -30,19 +30,28 @@ def __init__(self, inner: Microbench, outer: Microbench, threshold: MicrobenchCo def getMeasurements( self, - ) -> Dict[MicrobenchType, Dict[MicrobenchDimension, Dict[MicrobenchCoordinate, List[float]]],]: + ) -> Dict[ + MicrobenchType, + Dict[MicrobenchDimension, Dict[MicrobenchCoordinate, List[float]]], + ]: raise TypeError( "This MixedMicrobench might be based on two different sets of measurements. Use getInnerMeasurements() or getOuterMeasurements() instead." ) def getInnerMeasurements( self, - ) -> Dict[MicrobenchType, Dict[MicrobenchDimension, Dict[MicrobenchCoordinate, List[float]]],]: + ) -> Dict[ + MicrobenchType, + Dict[MicrobenchDimension, Dict[MicrobenchCoordinate, List[float]]], + ]: return self.inner.getMeasurements() def getOuterMeasurements( self, - ) -> Dict[MicrobenchType, Dict[MicrobenchDimension, Dict[MicrobenchCoordinate, List[float]]],]: + ) -> Dict[ + MicrobenchType, + Dict[MicrobenchDimension, Dict[MicrobenchCoordinate, List[float]]], + ]: return self.outer.getMeasurements() def toJSON(self) -> str: diff --git a/discopop_library/discopop_optimizer/Microbench/PureDataMicrobench.py b/discopop_library/discopop_optimizer/Microbench/PureDataMicrobench.py index 8d79d9a73..ee392bd5f 100644 --- a/discopop_library/discopop_optimizer/Microbench/PureDataMicrobench.py +++ b/discopop_library/discopop_optimizer/Microbench/PureDataMicrobench.py @@ -52,16 +52,17 @@ class PureDataMicrobench(Microbench): ] @overload - def __getitem__(self, key: MicrobenchType) -> Dict[MicrobenchDimension, Dict[MicrobenchCoordinate, List[float]]]: - ... + def __getitem__( + self, key: MicrobenchType + ) -> Dict[MicrobenchDimension, Dict[MicrobenchCoordinate, List[float]]]: ... @overload - def __getitem__(self, key: Tuple[MicrobenchType, MicrobenchDimension]) -> Dict[MicrobenchCoordinate, List[float]]: - ... + def __getitem__( + self, key: Tuple[MicrobenchType, MicrobenchDimension] + ) -> Dict[MicrobenchCoordinate, List[float]]: ... @overload - def __getitem__(self, key: Tuple[MicrobenchType, MicrobenchDimension, MicrobenchCoordinate]) -> List[float]: - ... + def __getitem__(self, key: Tuple[MicrobenchType, MicrobenchDimension, MicrobenchCoordinate]) -> List[float]: ... # allow to use this class like a dictionary def __getitem__(self, key: Any) -> Any: @@ -181,7 +182,10 @@ def mergeAll(self, others: List[PureDataMicrobench]) -> None: # inherited from Microbench def getMeasurements( self, - ) -> Dict[MicrobenchType, Dict[MicrobenchDimension, Dict[MicrobenchCoordinate, List[float]]],]: + ) -> Dict[ + MicrobenchType, + Dict[MicrobenchDimension, Dict[MicrobenchCoordinate, List[float]]], + ]: return self.measurements # inherited from Microbench diff --git a/discopop_library/discopop_optimizer/gui/presentation/OptionTable.py b/discopop_library/discopop_optimizer/gui/presentation/OptionTable.py index fbadb97fb..3dc05a5e5 100644 --- a/discopop_library/discopop_optimizer/gui/presentation/OptionTable.py +++ b/discopop_library/discopop_optimizer/gui/presentation/OptionTable.py @@ -212,12 +212,12 @@ def show_options( def __update_selection(cm: CostModel, ctx: ContextObject) -> None: experiment.selected_paths_per_function[function_root] = (cm, ctx) - experiment.substitutions[ - cast(Symbol, function_root.sequential_costs) - ] = experiment.selected_paths_per_function[function_root][0].sequential_costs - experiment.substitutions[ - cast(Symbol, function_root.parallelizable_costs) - ] = experiment.selected_paths_per_function[function_root][0].parallelizable_costs + experiment.substitutions[cast(Symbol, function_root.sequential_costs)] = ( + experiment.selected_paths_per_function[function_root][0].sequential_costs + ) + experiment.substitutions[cast(Symbol, function_root.parallelizable_costs)] = ( + experiment.selected_paths_per_function[function_root][0].parallelizable_costs + ) # update displayed value label2.configure(state=NORMAL) label2.delete(0, END) From eb3ba81e3742c7e168cadd1b1c2dd195fcf1f385 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Fri, 2 Aug 2024 08:44:51 +0200 Subject: [PATCH 080/105] fix: show test output --- test/utils/subprocess_wrapper/command_execution_wrapper.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/utils/subprocess_wrapper/command_execution_wrapper.py b/test/utils/subprocess_wrapper/command_execution_wrapper.py index 93ca4e370..b7e61e505 100644 --- a/test/utils/subprocess_wrapper/command_execution_wrapper.py +++ b/test/utils/subprocess_wrapper/command_execution_wrapper.py @@ -9,6 +9,6 @@ def run_cmd(cmd: str, cwd: str, env): executable="/bin/bash", shell=True, env=env, - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL, +# stdout=subprocess.DEVNULL, +# stderr=subprocess.DEVNULL, ) From 8f39372721a9505da3331c81dcb10232062c634c Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Fri, 2 Aug 2024 09:27:21 +0200 Subject: [PATCH 081/105] fix: add missing __init__.py --- discopop_explorer/functions/PEGraph/output/__init__.py | 0 discopop_explorer/functions/PEGraph/properties/__init__.py | 0 discopop_explorer/functions/PEGraph/queries/__init__.py | 0 test/utils/subprocess_wrapper/command_execution_wrapper.py | 4 ++-- 4 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 discopop_explorer/functions/PEGraph/output/__init__.py create mode 100644 discopop_explorer/functions/PEGraph/properties/__init__.py create mode 100644 discopop_explorer/functions/PEGraph/queries/__init__.py diff --git a/discopop_explorer/functions/PEGraph/output/__init__.py b/discopop_explorer/functions/PEGraph/output/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/discopop_explorer/functions/PEGraph/properties/__init__.py b/discopop_explorer/functions/PEGraph/properties/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/discopop_explorer/functions/PEGraph/queries/__init__.py b/discopop_explorer/functions/PEGraph/queries/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/utils/subprocess_wrapper/command_execution_wrapper.py b/test/utils/subprocess_wrapper/command_execution_wrapper.py index b7e61e505..5c7d3e127 100644 --- a/test/utils/subprocess_wrapper/command_execution_wrapper.py +++ b/test/utils/subprocess_wrapper/command_execution_wrapper.py @@ -9,6 +9,6 @@ def run_cmd(cmd: str, cwd: str, env): executable="/bin/bash", shell=True, env=env, -# stdout=subprocess.DEVNULL, -# stderr=subprocess.DEVNULL, + # stdout=subprocess.DEVNULL, + # stderr=subprocess.DEVNULL, ) From cecffbb1f30f5c3f7ad6135cc8ffaa70d861e70a Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Fri, 2 Aug 2024 09:29:46 +0200 Subject: [PATCH 082/105] fix: revert: show test output This reverts commit e8ea956ed4495d45d4c07be046984cc920a44a1a. --- test/utils/subprocess_wrapper/command_execution_wrapper.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/utils/subprocess_wrapper/command_execution_wrapper.py b/test/utils/subprocess_wrapper/command_execution_wrapper.py index 5c7d3e127..ec0a1b95d 100644 --- a/test/utils/subprocess_wrapper/command_execution_wrapper.py +++ b/test/utils/subprocess_wrapper/command_execution_wrapper.py @@ -2,13 +2,13 @@ from typing import Dict -def run_cmd(cmd: str, cwd: str, env): +def run_cmd(cmd: str, cwd: str, env: Dict[str, str]) -> None: subprocess.run( cmd, cwd=cwd, executable="/bin/bash", shell=True, env=env, - # stdout=subprocess.DEVNULL, - # stderr=subprocess.DEVNULL, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, ) From ca99b5e7326cbeb51a9e1818a3711e7d0a88e4bb Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Mon, 12 Aug 2024 10:06:13 +0200 Subject: [PATCH 083/105] feat: add distinguished behavior to reduction and doall detector --- .../classes/PEGraph/Dependency.py | 12 +- .../pattern_detectors/do_all_detector.py | 153 +++++++++++------- .../pattern_detectors/reduction_detector.py | 100 +++++++----- .../PEGraphConstructionUtilities.py | 24 ++- .../utilities/PEGraphConstruction/parser.py | 10 +- discopop_explorer/utils.py | 15 +- .../EmpiricalAutotuning/Autotuner.py | 5 +- 7 files changed, 192 insertions(+), 127 deletions(-) diff --git a/discopop_explorer/classes/PEGraph/Dependency.py b/discopop_explorer/classes/PEGraph/Dependency.py index e9e7429ab..3c91b6a8c 100644 --- a/discopop_explorer/classes/PEGraph/Dependency.py +++ b/discopop_explorer/classes/PEGraph/Dependency.py @@ -25,12 +25,12 @@ class Dependency: sink_line: Optional[LineID] = None intra_iteration: bool = False intra_iteration_level: int = -1 - metadata_intra_iteration_dep: List[LineID] - metadata_inter_iteration_dep: List[LineID] - metadata_intra_call_dep: List[LineID] - metadata_inter_call_dep: List[LineID] - metadata_sink_ancestors: List[LineID] - metadata_source_ancestors: List[LineID] + metadata_intra_iteration_dep: Optional[List[LineID]] + metadata_inter_iteration_dep: Optional[List[LineID]] + metadata_intra_call_dep: Optional[List[LineID]] + metadata_inter_call_dep: Optional[List[LineID]] + metadata_sink_ancestors: Optional[List[LineID]] + metadata_source_ancestors: Optional[List[LineID]] def __init__(self, type: EdgeType): self.etype = type diff --git a/discopop_explorer/pattern_detectors/do_all_detector.py b/discopop_explorer/pattern_detectors/do_all_detector.py index a7c2181ea..00eb620f0 100644 --- a/discopop_explorer/pattern_detectors/do_all_detector.py +++ b/discopop_explorer/pattern_detectors/do_all_detector.py @@ -97,8 +97,6 @@ def run_detection( result: List[DoAllInfo] = [] nodes = all_nodes(pet, LoopNode) - warnings.warn("DOALL DETECTION CURRENTLY ASSUMES THE EXISTENCE OF DEPENDENCY METADATA!") - # remove reduction loops print("ASDF: ", [r.node_id for r in reduction_info]) print("Nodes: ", [n.start_position() for n in nodes]) @@ -283,14 +281,15 @@ def __check_loop_dependencies( if is_loop_index(pet, dep.var_name, loop_start_lines, root_children_cus): continue - # ignore dependencies where either source or sink do not lie within root_loop - if len(dep.metadata_source_ancestors) > 0 and len(dep.metadata_sink_ancestors) > 0: - if not ( - (root_loop.start_position() in dep.metadata_sink_ancestors) - and root_loop.start_position() in dep.metadata_source_ancestors - ): - tmp = root_loop.start_position() - continue + # if metadata exists, ignore dependencies where either source or sink do not lie within root_loop + if dep.metadata_source_ancestors is not None and dep.metadata_sink_ancestors is not None: + if len(dep.metadata_source_ancestors) > 0 and len(dep.metadata_sink_ancestors) > 0: + if not ( + (root_loop.start_position() in dep.metadata_sink_ancestors) + and root_loop.start_position() in dep.metadata_source_ancestors + ): + tmp = root_loop.start_position() + continue # targeted variable is not read-only if dep.dtype == DepType.INIT: @@ -298,66 +297,96 @@ def __check_loop_dependencies( elif dep.dtype == DepType.RAW: # check RAW dependencies # RAW problematic, if it is not an intra-iteration RAW - cond_1 = (len(dep.metadata_intra_iteration_dep) == 0) and parent_function_lineid in ( - dep.metadata_intra_call_dep if dep.metadata_intra_call_dep is not None else [] - ) - cond_2 = len([cf for cf in called_functions_lineids if cf in dep.metadata_inter_call_dep]) > 0 - cond_3 = len([t for t in parent_loops if t in dep.metadata_inter_iteration_dep]) > 0 - if cond_1 or cond_2 or cond_3: - return True - # if it is an intra iteration dependency, it is problematic if it belongs to a parent loop - else: - if dep.intra_iteration_level <= max_considered_intra_iteration_dep_level: - if pet.node_at(source) in root_children_cus and pet.node_at(target) in root_children_cus: - pass - else: - # check if metadata exists - if dep.metadata_intra_iteration_dep is not None: - for t in dep.metadata_intra_iteration_dep: - if t in parent_loops: - return True - return False + if ( + dep.metadata_intra_iteration_dep is None + or dep.metadata_inter_iteration_dep is None + or dep.metadata_intra_call_dep is None + or dep.metadata_inter_call_dep is None + ): + # no metadata created + if not dep.intra_iteration: + return True + else: + if dep.intra_iteration_level <= max_considered_intra_iteration_dep_level: + if pet.node_at(source) in root_children_cus and pet.node_at(target) in root_children_cus: + pass else: return True + else: + # metadata exists + cond_1 = (len(dep.metadata_intra_iteration_dep) == 0) and parent_function_lineid in ( + dep.metadata_intra_call_dep if dep.metadata_intra_call_dep is not None else [] + ) + cond_2 = len([cf for cf in called_functions_lineids if cf in dep.metadata_inter_call_dep]) > 0 + cond_3 = len([t for t in parent_loops if t in dep.metadata_inter_iteration_dep]) > 0 + if cond_1 or cond_2 or cond_3: + return True + # if it is an intra iteration dependency, it is problematic if it belongs to a parent loop + else: + if dep.intra_iteration_level <= max_considered_intra_iteration_dep_level: + if pet.node_at(source) in root_children_cus and pet.node_at(target) in root_children_cus: + pass + else: + # check if metadata exists + if dep.metadata_intra_iteration_dep is not None: + for t in dep.metadata_intra_iteration_dep: + if t in parent_loops: + return True + return False + else: + return True elif dep.dtype == DepType.WAR: # check WAR dependencies # WAR problematic, if it is not an intra-iteration WAR and the variable is not private or firstprivate - if ( - not dep.intra_iteration - and (dep.metadata_intra_iteration_dep is None or len(dep.metadata_intra_iteration_dep) == 0) - and parent_function_lineid - in (dep.metadata_intra_call_dep if dep.metadata_intra_call_dep is not None else []) - ) or ( - ( - False - if dep.metadata_inter_call_dep is None - else (len([cf for cf in called_functions_lineids if cf in dep.metadata_inter_call_dep]) > 0) - ) - and ( - False - if dep.metadata_inter_iteration_dep is None - else (len([t for t in parent_loops if t in dep.metadata_inter_iteration_dep]) > 0) - ) - ): - if dep.var_name not in [v.name for v in first_privates + privates + last_privates]: - # check if variable is defined inside loop - if dep.memory_region not in memory_regions_defined_in_loop: - return True - # check if the definitions of the accessed variable originates from a function call - if __check_for_problematic_function_argument_access(pet, source, target, dep): - return True - # if it is an intra iteration dependency, it is problematic if it belongs to a parent loop - elif dep.intra_iteration_level > root_loop.get_nesting_level(pet): - tmp_nesting_level = root_loop.get_nesting_level(pet) - # check if metadata exists - if len(dep.metadata_intra_iteration_dep) != 0: - for t in dep.metadata_intra_iteration_dep: - if t in parent_loops: + if dep.metadata_intra_iteration_dep is None: + # no metadata created + if not dep.intra_iteration: + if dep.var_name not in [v.name for v in first_privates + privates + last_privates]: + # check if variable is defined inside loop + if dep.memory_region not in memory_regions_defined_in_loop: return True - return False - else: + # if it is an intra iteration dependency, it is problematic if it belongs to a parent loop + elif dep.intra_iteration_level > root_loop.get_nesting_level(pet): return True + + else: + # metadata exists + if ( + not dep.intra_iteration + and (dep.metadata_intra_iteration_dep is None or len(dep.metadata_intra_iteration_dep) == 0) + and parent_function_lineid + in (dep.metadata_intra_call_dep if dep.metadata_intra_call_dep is not None else []) + ) or ( + ( + False + if dep.metadata_inter_call_dep is None + else (len([cf for cf in called_functions_lineids if cf in dep.metadata_inter_call_dep]) > 0) + ) + and ( + False + if dep.metadata_inter_iteration_dep is None + else (len([t for t in parent_loops if t in dep.metadata_inter_iteration_dep]) > 0) + ) + ): + if dep.var_name not in [v.name for v in first_privates + privates + last_privates]: + # check if variable is defined inside loop + if dep.memory_region not in memory_regions_defined_in_loop: + return True + # check if the definitions of the accessed variable originates from a function call + if __check_for_problematic_function_argument_access(pet, source, target, dep): + return True + # if it is an intra iteration dependency, it is problematic if it belongs to a parent loop + elif dep.intra_iteration_level > root_loop.get_nesting_level(pet): + tmp_nesting_level = root_loop.get_nesting_level(pet) + # check if metadata exists + if len(dep.metadata_intra_iteration_dep) != 0: + for t in dep.metadata_intra_iteration_dep: + if t in parent_loops: + return True + return False + else: + return True elif dep.dtype == DepType.WAW: # check WAW dependencies # handled by variable classification diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index bfb98a1d6..21d8960b1 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -91,8 +91,6 @@ def run_detection( nodes = cast(List[LoopNode], filter_for_hotspots(pet, cast(List[Node], nodes), hotspots)) - warnings.warn("REDUCTION DETECTION CURRENTLY ASSUMES THE EXISTENCE OF DEPENDENCY METADATA!") - param_list = [(node) for node in nodes] with Pool(initializer=__initialize_worker, initargs=(pet,)) as pool: tmp_result = list(tqdm.tqdm(pool.imap_unordered(__check_node, param_list), total=len(param_list))) @@ -243,14 +241,15 @@ def __check_loop_dependencies( if is_loop_index(pet, dep.var_name, loop_start_lines, root_children_cus): continue - # ignore dependencies where either source or sink do not lie within root_loop - if len(dep.metadata_source_ancestors) > 0 and len(dep.metadata_sink_ancestors) > 0: - if not ( - (root_loop.start_position() in dep.metadata_sink_ancestors) - and root_loop.start_position() in dep.metadata_source_ancestors - ): - tmp = root_loop.start_position() - continue + # if metadata exists, ignore dependencies where either source or sink do not lie within root_loop + if dep.metadata_source_ancestors is not None and dep.metadata_sink_ancestors is not None: + if len(dep.metadata_source_ancestors) > 0 and len(dep.metadata_sink_ancestors) > 0: + if not ( + (root_loop.start_position() in dep.metadata_sink_ancestors) + and root_loop.start_position() in dep.metadata_source_ancestors + ): + tmp = root_loop.start_position() + continue # targeted variable is not read-only if dep.dtype == DepType.INIT: @@ -269,42 +268,59 @@ def __check_loop_dependencies( else: # RAW does not target a reduction variable. # RAW problematic, if it is not an intra-iteration RAW. - cond_1 = (len(dep.metadata_intra_iteration_dep) == 0) and parent_function_lineid in ( - dep.metadata_intra_call_dep if dep.metadata_intra_call_dep is not None else [] - ) - cond_2 = len([cf for cf in called_functions_lineids if cf in dep.metadata_inter_call_dep]) > 0 - cond_3 = len([t for t in parent_loops if t in dep.metadata_inter_iteration_dep]) > 0 - if cond_1 or cond_2 or cond_3: - return True - # check for + if ( + dep.metadata_intra_iteration_dep is None + or dep.metadata_inter_iteration_dep is None + or dep.metadata_intra_call_dep is None + or dep.metadata_inter_call_dep is None + ): + # no metadata generated + if not dep.intra_iteration: + return True + else: + # metadata exist + cond_1 = (len(dep.metadata_intra_iteration_dep) == 0) and parent_function_lineid in ( + dep.metadata_intra_call_dep if dep.metadata_intra_call_dep is not None else [] + ) + cond_2 = len([cf for cf in called_functions_lineids if cf in dep.metadata_inter_call_dep]) > 0 + cond_3 = len([t for t in parent_loops if t in dep.metadata_inter_iteration_dep]) > 0 + if cond_1 or cond_2 or cond_3: + return True elif dep.dtype == DepType.WAR: # check WAR dependencies # WAR problematic, if it is not an intra-iteration WAR and the variable is not private or firstprivate - if ( - not dep.intra_iteration - and (dep.metadata_intra_iteration_dep is None or len(dep.metadata_intra_iteration_dep) == 0) - and parent_function_lineid - in (dep.metadata_intra_call_dep if dep.metadata_intra_call_dep is not None else []) - ) or ( - ( - False - if dep.metadata_inter_call_dep is None - else (len([cf for cf in called_functions_lineids if cf in dep.metadata_inter_call_dep]) > 0) - ) - and ( - False - if dep.metadata_inter_iteration_dep is None - else (len([t for t in parent_loops if t in dep.metadata_inter_iteration_dep]) > 0) - ) - ): - if dep.var_name not in [v.name for v in first_privates + privates + last_privates]: - # check if variable is defined inside loop - if dep.memory_region not in memory_regions_defined_in_loop: - return True - # check if the definitions of the accessed variable originates from a function call - if __check_for_problematic_function_argument_access(pet, source, target, dep): - pass + if dep.metadata_intra_iteration_dep is None: + # no metadata generated + if not dep.intra_iteration: + if dep.var_name not in [v.name for v in first_privates + privates + last_privates]: return True + else: + # metadata exists + if ( + not dep.intra_iteration + and (dep.metadata_intra_iteration_dep is None or len(dep.metadata_intra_iteration_dep) == 0) + and parent_function_lineid + in (dep.metadata_intra_call_dep if dep.metadata_intra_call_dep is not None else []) + ) or ( + ( + False + if dep.metadata_inter_call_dep is None + else (len([cf for cf in called_functions_lineids if cf in dep.metadata_inter_call_dep]) > 0) + ) + and ( + False + if dep.metadata_inter_iteration_dep is None + else (len([t for t in parent_loops if t in dep.metadata_inter_iteration_dep]) > 0) + ) + ): + if dep.var_name not in [v.name for v in first_privates + privates + last_privates]: + # check if variable is defined inside loop + if dep.memory_region not in memory_regions_defined_in_loop: + return True + # check if the definitions of the accessed variable originates from a function call + if __check_for_problematic_function_argument_access(pet, source, target, dep): + pass + return True elif dep.dtype == DepType.WAW: # check WAW dependencies # handled by variable classification diff --git a/discopop_explorer/utilities/PEGraphConstruction/PEGraphConstructionUtilities.py b/discopop_explorer/utilities/PEGraphConstruction/PEGraphConstructionUtilities.py index b3dc60666..0213e3d40 100644 --- a/discopop_explorer/utilities/PEGraphConstruction/PEGraphConstructionUtilities.py +++ b/discopop_explorer/utilities/PEGraphConstruction/PEGraphConstructionUtilities.py @@ -8,10 +8,11 @@ from __future__ import annotations -from typing import Union +from typing import List, Union, cast from lxml.objectify import ObjectifiedElement # type: ignore +from discopop_explorer.aliases.LineID import LineID from discopop_explorer.classes.PEGraph.CUNode import CUNode from discopop_explorer.classes.PEGraph.Dependency import Dependency @@ -41,7 +42,16 @@ def parse_dependency(dep: DependenceItem) -> Dependency: d.dtype = DepType[dep.type] d.var_name = dep.var_name d.memory_region = dep.memory_region + # parse metadata + if dep.metadata is None: + d.metadata_intra_iteration_dep = None + d.metadata_inter_iteration_dep = None + d.metadata_intra_call_dep = None + d.metadata_inter_call_dep = None + d.metadata_sink_ancestors = None + d.metadata_source_ancestors = None + return d if len(dep.metadata) > 0: for md in dep.metadata.split(" "): if len(md) == 0: @@ -50,6 +60,18 @@ def parse_dependency(dep: DependenceItem) -> Dependency: md_type = md[: md.index("[")] md_raw_values = md[md.index("[") + 1 : -1] md_values = [tmp for tmp in md_raw_values.split(",") if len(tmp) > 0] + + # ensure validity and type correctness + if ( + d.metadata_intra_iteration_dep is None + or d.metadata_inter_iteration_dep is None + or d.metadata_intra_call_dep is None + or d.metadata_inter_call_dep is None + or d.metadata_sink_ancestors is None + or d.metadata_source_ancestors is None + ): + raise ValueError("Invalid data found!") + # store metadata if md_type == "IAI": d.metadata_intra_iteration_dep += md_values diff --git a/discopop_explorer/utilities/PEGraphConstruction/parser.py b/discopop_explorer/utilities/PEGraphConstruction/parser.py index 3d2da59af..260388c7d 100644 --- a/discopop_explorer/utilities/PEGraphConstruction/parser.py +++ b/discopop_explorer/utilities/PEGraphConstruction/parser.py @@ -99,10 +99,12 @@ def __parse_dep_file(dep_fd: TextIOWrapper, output_path: str) -> Tuple[List[Depe loop_data_list: List[LoopData] = [] # read dependency metadata + metadata_exists: bool = False dependency_metadata_lines = [] if os.path.exists(os.path.join(output_path, "dependency_metadata.txt")): with open(os.path.join(output_path, "dependency_metadata.txt"), "r") as dep_metadata_fd: dependency_metadata_lines = dep_metadata_fd.readlines() + metadata_exists = True dependency_metadata: Dict[Tuple[Any, Any, Any, Any, Any], List[str]] = dict() for line in dependency_metadata_lines: line = line.replace("\n", "") @@ -164,7 +166,7 @@ def __parse_dep_file(dep_fd: TextIOWrapper, output_path: str) -> Tuple[List[Depe var_str = "" if len(source_fields) == 1 else source_fields[1] var_name = "" aa_var_name = "" - metadata = [] + metadata: Optional[List[str]] = [] if metadata_exists else None if len(var_str) > 0: if "(" in var_str: split_var_str = var_str.split("(") @@ -187,6 +189,12 @@ def __parse_dep_file(dep_fd: TextIOWrapper, output_path: str) -> Tuple[List[Depe is_gep_result_dependency = True # register dependencies + if metadata is None: + dependencies_list.append( + DependenceItem(sink, source_fields[0], type, var_name, aa_var_name, is_gep_result_dependency, None) + ) + continue + if len(metadata) == 0: dependencies_list.append( DependenceItem(sink, source_fields[0], type, var_name, aa_var_name, is_gep_result_dependency, "") diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index 89d4a14b9..afdeaab38 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -848,8 +848,9 @@ def no_inter_iteration_dependency_exists( for dep in raw.union(war): if dep[0] in [s.id for s in sub] and dep[1] in [s.id for s in sub]: if dep[2].memory_region in mem_regs: - if root_loop.start_position() in dep[2].metadata_inter_iteration_dep: - return False + if dep[2].metadata_inter_iteration_dep is not None: + if root_loop.start_position() in dep[2].metadata_inter_iteration_dep: + return False return True @@ -927,15 +928,7 @@ def classify_task_vars( in_deps: List[Tuple[NodeID, NodeID, Dependency]], out_deps: List[Tuple[NodeID, NodeID, Dependency]], used_in_task_parallelism_detection: bool = False, -) -> Tuple[ - List[Variable], - List[Variable], - List[Variable], - List[Variable], - List[Variable], - List[Variable], - List[str], -]: +) -> Tuple[List[Variable], List[Variable], List[Variable], List[Variable], List[Variable], List[Variable], List[str]]: """Classify task variables :param pet: CU graph diff --git a/discopop_library/EmpiricalAutotuning/Autotuner.py b/discopop_library/EmpiricalAutotuning/Autotuner.py index f63078cb3..3223a1957 100644 --- a/discopop_library/EmpiricalAutotuning/Autotuner.py +++ b/discopop_library/EmpiricalAutotuning/Autotuner.py @@ -121,10 +121,7 @@ def run(arguments: AutotunerArguments) -> None: continue visited_configurations.append(current_config) tmp_config = reference_configuration.create_copy(get_unique_configuration_id) - try: - tmp_config.apply_suggestions(arguments, current_config) - except ValueError: - continue + tmp_config.apply_suggestions(arguments, current_config) tmp_config.execute(timeout=timeout_after) statistics_graph.add_child( "step " From 2824197173b96f851900546e6a6d438edfec2d36 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Mon, 19 Aug 2024 11:18:14 +0200 Subject: [PATCH 084/105] feat(autotuner): skip loops with runtime contribution < 1 % --- discopop_library/EmpiricalAutotuning/Autotuner.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/discopop_library/EmpiricalAutotuning/Autotuner.py b/discopop_library/EmpiricalAutotuning/Autotuner.py index 3223a1957..43b751c9f 100644 --- a/discopop_library/EmpiricalAutotuning/Autotuner.py +++ b/discopop_library/EmpiricalAutotuning/Autotuner.py @@ -16,7 +16,7 @@ from discopop_library.EmpiricalAutotuning.ArgumentClasses import AutotunerArguments from discopop_library.EmpiricalAutotuning.Classes.CodeConfiguration import CodeConfiguration from discopop_library.EmpiricalAutotuning.Classes.ExecutionResult import ExecutionResult -from discopop_library.EmpiricalAutotuning.Statistics.StatisticsGraph import NodeShape, StatisticsGraph +from discopop_library.EmpiricalAutotuning.Statistics.StatisticsGraph import NodeColor, NodeShape, StatisticsGraph from discopop_library.EmpiricalAutotuning.Types import SUGGESTION_ID from discopop_library.EmpiricalAutotuning.utils import get_applicable_suggestion_ids from discopop_library.HostpotLoader.HotspotLoaderArguments import HotspotLoaderArguments @@ -107,10 +107,20 @@ def run(arguments: AutotunerArguments) -> None: + str(round(loop_tuple[4], 3)) + "s" ) - statistics_graph.add_child(loop_str) + # check if the loop contributes more than 1% to the total runtime + loop_contributes_significantly = loop_tuple[4] > ( + cast(ExecutionResult, reference_configuration.execution_result).runtime / 100 + ) + if not loop_contributes_significantly: + statistics_graph.add_child(loop_str, color=NodeColor.ORANGE) + else: + statistics_graph.add_child(loop_str) statistics_graph.update_current_node(loop_str) # identify all applicable suggestions for this loop logger.debug(str(hotspot_type) + " loop: " + str(loop_tuple)) + if not loop_contributes_significantly: + logger.debug("--> Skipping loop due to runtime contribution < 1%") + continue # create code and execute for all applicable suggestions applicable_suggestions = get_applicable_suggestion_ids(loop_tuple[0], loop_tuple[1], detection_result) logger.debug("--> applicable suggestions: " + str(applicable_suggestions)) From 1c48575f7623cf290c8984a2666e7d03a6ff7dc7 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Mon, 12 Aug 2024 16:03:19 +0200 Subject: [PATCH 085/105] fix: implemented TODO targeting InvokeInst --- DiscoPoP/static_analysis/createCUs.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/DiscoPoP/static_analysis/createCUs.cpp b/DiscoPoP/static_analysis/createCUs.cpp index 3f972fc5f..fcf09a27d 100644 --- a/DiscoPoP/static_analysis/createCUs.cpp +++ b/DiscoPoP/static_analysis/createCUs.cpp @@ -203,10 +203,9 @@ void DiscoPoP::createCUs(Region *TopRegion, set &globalVariablesSet, vec cu->readPhaseLineNumbers.insert(lid); } } - } else if (isa(instruction)) { + } else if (isa(instruction) || isa(instruction)) { // get the name of the called function and check if a FileIO function // is called - CallInst *ci = cast(instruction); set IOFunctions{ "fopen", "fopen_s", "freopen", "freopen_s", "fclose", "fflush", "setbuf", "setvbuf", "fwide", "fread", "fwrite", "fgetc", "getc", "fgets", @@ -223,6 +222,8 @@ void DiscoPoP::createCUs(Region *TopRegion, set &globalVariablesSet, vec "vswprintf_s", "vsnwprintf_s", "ftell", "fgetpos", "fseek", "fsetpos", "rewind", "clearerr", "feof", "ferror", "perror", "remove", "rename", "tmpfile", "tmpfile_s", "tmpnam", "tmpnam_s", "__isoc99_fscanf"}; + + CallBase *ci = cast(instruction); if (ci) { if (ci->getCalledFunction()) { if (ci->getCalledFunction()->hasName()) { @@ -255,10 +256,17 @@ void DiscoPoP::createCUs(Region *TopRegion, set &globalVariablesSet, vec // Note: Don't create nodes for library functions (c++/llvm). LID lid = getLID(&*instruction, fileID); if (lid > 0) { - if (isa(instruction)) { - CallInst *ci = cast(instruction); - Function *f = ci->getCalledFunction(); - // TODO: DO the same for Invoke inst + if (isa(instruction) || isa(instruction)) { + Function *f; + + if(isa(instruction)){ + CallInst *ci = cast(instruction); + f = ci->getCalledFunction(); + } + else if(isa(instruction)){ + InvokeInst *ci = cast(instruction); + f = ci->getCalledFunction(); + } string lid; if (f) { From 024c47de19f92ddef28ae147505f72d442079114 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 20 Aug 2024 09:51:48 +0200 Subject: [PATCH 086/105] feat(autotuner): adaptive timeout --- discopop_library/EmpiricalAutotuning/Autotuner.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/discopop_library/EmpiricalAutotuning/Autotuner.py b/discopop_library/EmpiricalAutotuning/Autotuner.py index 43b751c9f..9ec0f90ca 100644 --- a/discopop_library/EmpiricalAutotuning/Autotuner.py +++ b/discopop_library/EmpiricalAutotuning/Autotuner.py @@ -192,6 +192,13 @@ def run(arguments: AutotunerArguments) -> None: + " stored at " + best_suggestion_configuration[1].root_path ) + # update the timeout according to the new time measurement + timeout_after = max( + 3.0, cast(ExecutionResult, best_suggestion_configuration[1].execution_result).runtime * 2 + ) + logger.debug("Updated timeout to: " + str(round(timeout_after, 3))) + + # update the graph and store the current best configuration statistics_graph.add_child( "step " + str(statistics_step_num) From 3872b4fef5d3daed104e7bd6b37766d8bb60e4fd Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 20 Aug 2024 15:21:11 +0200 Subject: [PATCH 087/105] feat: add utility: GEPDependencyRemover --- .../GEPDependencyRemover/ArgumentClasses.py | 39 +++++++++++++ .../GEPDependencyRemover.py | 56 +++++++++++++++++++ .../GEPDependencyRemover/Types.py | 9 +++ .../GEPDependencyRemover/__init__.py | 0 .../GEPDependencyRemover/__main__.py | 44 +++++++++++++++ .../GEPDependencyRemover/utils.py | 25 +++++++++ .../Compatibility/LegacyDiscoPoP/__init__.py | 0 7 files changed, 173 insertions(+) create mode 100644 discopop_library/Compatibility/LegacyDiscoPoP/GEPDependencyRemover/ArgumentClasses.py create mode 100644 discopop_library/Compatibility/LegacyDiscoPoP/GEPDependencyRemover/GEPDependencyRemover.py create mode 100644 discopop_library/Compatibility/LegacyDiscoPoP/GEPDependencyRemover/Types.py create mode 100644 discopop_library/Compatibility/LegacyDiscoPoP/GEPDependencyRemover/__init__.py create mode 100644 discopop_library/Compatibility/LegacyDiscoPoP/GEPDependencyRemover/__main__.py create mode 100644 discopop_library/Compatibility/LegacyDiscoPoP/GEPDependencyRemover/utils.py create mode 100644 discopop_library/Compatibility/LegacyDiscoPoP/__init__.py diff --git a/discopop_library/Compatibility/LegacyDiscoPoP/GEPDependencyRemover/ArgumentClasses.py b/discopop_library/Compatibility/LegacyDiscoPoP/GEPDependencyRemover/ArgumentClasses.py new file mode 100644 index 000000000..b1e98c2d2 --- /dev/null +++ b/discopop_library/Compatibility/LegacyDiscoPoP/GEPDependencyRemover/ArgumentClasses.py @@ -0,0 +1,39 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from dataclasses import dataclass +import logging +import os +from discopop_library.ArgumentClasses.GeneralArguments import GeneralArguments + +logger = logging.getLogger("AutotunerArguments") + + +@dataclass +class GEPDependencyRemoverArguments(GeneralArguments): + """Container Class for the arguments passed to the discopop GEPDependencyRemover""" + + dyndep_file_path: str + + def __post_init__(self) -> None: + self.__validate() + + def log(self) -> None: + logger.debug("Arguments:") + for entry in self.__dict__: + logger.debug("-- " + str(entry) + ": " + str(self.__dict__[entry])) + + def __validate(self) -> None: + """Validate the arguments passed to the discopop GEPDependencyRemover, e.g check if given files exist""" + + required_files = [ + self.dyndep_file_path, + ] + for file in required_files: + if not os.path.exists(file): + raise FileNotFoundError(file) diff --git a/discopop_library/Compatibility/LegacyDiscoPoP/GEPDependencyRemover/GEPDependencyRemover.py b/discopop_library/Compatibility/LegacyDiscoPoP/GEPDependencyRemover/GEPDependencyRemover.py new file mode 100644 index 000000000..2dcabb1a0 --- /dev/null +++ b/discopop_library/Compatibility/LegacyDiscoPoP/GEPDependencyRemover/GEPDependencyRemover.py @@ -0,0 +1,56 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +import logging +import os +import re +from typing import List, Tuple, cast + +import jsonpickle # type: ignore +from discopop_explorer.classes.PEGraph.LoopNode import LoopNode +from discopop_explorer.functions.PEGraph.queries.nodes import all_nodes +from discopop_library.Compatibility.LegacyDiscoPoP.GEPDependencyRemover.ArgumentClasses import ( + GEPDependencyRemoverArguments, +) +from discopop_library.EmpiricalAutotuning.Classes.CodeConfiguration import CodeConfiguration +from discopop_library.EmpiricalAutotuning.Classes.ExecutionResult import ExecutionResult +from discopop_library.EmpiricalAutotuning.Statistics.StatisticsGraph import NodeColor, NodeShape, StatisticsGraph +from discopop_library.EmpiricalAutotuning.Types import SUGGESTION_ID +from discopop_library.EmpiricalAutotuning.utils import get_applicable_suggestion_ids +from discopop_library.HostpotLoader.HotspotLoaderArguments import HotspotLoaderArguments +from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType +from discopop_library.HostpotLoader.HotspotType import HotspotType +from discopop_library.HostpotLoader.hostpot_loader import run as load_hotspots +from discopop_library.result_classes.DetectionResult import DetectionResult + +logger = logging.getLogger("GEPDependencyRemover") + + +def run(arguments: GEPDependencyRemoverArguments) -> None: + logger.info("Starting DiscoPoP GEPDependencyRemover.") + + filtered_lines: List[str] = [] + + # unpack dynamic dependency file + with open(arguments.dyndep_file_path, "r") as dyn_dep_file: + for line in dyn_dep_file.readlines(): + line = line.replace("\n", "") + # unpack line and remove GEPRESULT dependencies + logger.debug("line: \t" + line) + line = re.sub(r"((RAW)|(WAR)|(WAW)|(INIT))\s+[\*(\d+\:\d+)]+\|\S+\(GEPRESULT_\S+\)\s*", "", line) + logger.debug("Line post:\t" + line) + line = line + "\n" + filtered_lines.append(line) + logger.debug("") + + # write the updated file + logger.info("Overwriting " + arguments.dyndep_file_path) + with open(arguments.dyndep_file_path, "w") as dyn_dep_file: + for line in filtered_lines: + dyn_dep_file.write(line) + logger.info("Done writing " + arguments.dyndep_file_path) diff --git a/discopop_library/Compatibility/LegacyDiscoPoP/GEPDependencyRemover/Types.py b/discopop_library/Compatibility/LegacyDiscoPoP/GEPDependencyRemover/Types.py new file mode 100644 index 000000000..53826db30 --- /dev/null +++ b/discopop_library/Compatibility/LegacyDiscoPoP/GEPDependencyRemover/Types.py @@ -0,0 +1,9 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +SUGGESTION_ID = int diff --git a/discopop_library/Compatibility/LegacyDiscoPoP/GEPDependencyRemover/__init__.py b/discopop_library/Compatibility/LegacyDiscoPoP/GEPDependencyRemover/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/discopop_library/Compatibility/LegacyDiscoPoP/GEPDependencyRemover/__main__.py b/discopop_library/Compatibility/LegacyDiscoPoP/GEPDependencyRemover/__main__.py new file mode 100644 index 000000000..7a064e322 --- /dev/null +++ b/discopop_library/Compatibility/LegacyDiscoPoP/GEPDependencyRemover/__main__.py @@ -0,0 +1,44 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from argparse import ArgumentParser +import os +from discopop_library.Compatibility.LegacyDiscoPoP.GEPDependencyRemover.ArgumentClasses import ( + GEPDependencyRemoverArguments, +) +from discopop_library.GlobalLogger.setup import setup_logger +from discopop_library.Compatibility.LegacyDiscoPoP.GEPDependencyRemover.GEPDependencyRemover import run + + +def parse_args() -> GEPDependencyRemoverArguments: + """Parse the arguments passed to the discopop GEPDependencyRemover""" + parser = ArgumentParser(description="DiscoPoP GEPDependencyRemover") + + # fmt: off + + parser.add_argument("--log", type=str, default="WARNING", help="Specify log level: DEBUG, INFO, WARNING, ERROR, CRITICAL") + parser.add_argument("--write-log", action="store_true", help="Create Logfile.") + parser.add_argument("--dyndep-file-path", type=str, default=os.path.join(os.getcwd(), ".discopop", "profiler", "dynamic_dependencies.txt"), help="Path to the dynamic dependencies file to be converted.") + # fmt: on + + arguments = parser.parse_args() + + return GEPDependencyRemoverArguments( + log_level=arguments.log.upper(), write_log=arguments.write_log, dyndep_file_path=arguments.dyndep_file_path + ) + + +def main() -> None: + arguments = parse_args() + setup_logger(arguments) + arguments.log() + run(arguments) + + +if __name__ == "__main__": + main() diff --git a/discopop_library/Compatibility/LegacyDiscoPoP/GEPDependencyRemover/utils.py b/discopop_library/Compatibility/LegacyDiscoPoP/GEPDependencyRemover/utils.py new file mode 100644 index 000000000..d86d56706 --- /dev/null +++ b/discopop_library/Compatibility/LegacyDiscoPoP/GEPDependencyRemover/utils.py @@ -0,0 +1,25 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +import logging +from typing import List + +from discopop_library.EmpiricalAutotuning.Types import SUGGESTION_ID +from discopop_library.result_classes.DetectionResult import DetectionResult + +logger = logging.getLogger("uitls") + + +def get_applicable_suggestion_ids(file_id: int, start_line: int, dtres: DetectionResult) -> List[SUGGESTION_ID]: + """Identify suggestions where start position matches the given start position and return their ids.""" + res: List[int] = [] + for pattern_type in dtres.patterns.__dict__: + for pattern in dtres.patterns.__dict__[pattern_type]: + if pattern.start_line == str(file_id) + ":" + str(start_line) and pattern.applicable_pattern: + res.append(pattern.pattern_id) + return res diff --git a/discopop_library/Compatibility/LegacyDiscoPoP/__init__.py b/discopop_library/Compatibility/LegacyDiscoPoP/__init__.py new file mode 100644 index 000000000..e69de29bb From 7eb0b05827f633a6ccb3b90c09899f05c95851a1 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 21 Aug 2024 16:04:17 +0200 Subject: [PATCH 088/105] fix: minor --- discopop_library/LineMapping/diff_modifications.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/discopop_library/LineMapping/diff_modifications.py b/discopop_library/LineMapping/diff_modifications.py index 3d9cf6583..8d8ae1b32 100644 --- a/discopop_library/LineMapping/diff_modifications.py +++ b/discopop_library/LineMapping/diff_modifications.py @@ -50,7 +50,13 @@ def apply_line_mapping_modifications_from_diff(file_id: int, diff: str) -> None: # get cleaned diff cleaned_diff: List[str] = [] for line in diff.split("\n"): - if line.startswith("<") or line.startswith(">") or line.startswith("-") or len(line) == 0: + if ( + line.startswith("<") + or line.startswith(">") + or line.startswith("-") + or line.startswith("\\") + or len(line) == 0 + ): continue line = line.replace("\n", "") cleaned_diff.append(line) From b6c4e71647e8aeada2c91e9f46591319733fa0fe Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Mon, 26 Aug 2024 13:20:07 +0200 Subject: [PATCH 089/105] fix(autotuner): consider result validity in plotting --- .../EmpiricalAutotuning/Autotuner.py | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/discopop_library/EmpiricalAutotuning/Autotuner.py b/discopop_library/EmpiricalAutotuning/Autotuner.py index 9ec0f90ca..79f05e69c 100644 --- a/discopop_library/EmpiricalAutotuning/Autotuner.py +++ b/discopop_library/EmpiricalAutotuning/Autotuner.py @@ -39,7 +39,7 @@ def get_unique_configuration_id() -> int: def run(arguments: AutotunerArguments) -> None: logger.info("Starting discopop autotuner.") - debug_stats: List[Tuple[List[SUGGESTION_ID], float, int, str]] = [] + debug_stats: List[Tuple[List[SUGGESTION_ID], float, int, bool, str]] = [] statistics_graph = StatisticsGraph() statistics_step_num = 0 @@ -57,6 +57,7 @@ def run(arguments: AutotunerArguments) -> None: [], cast(ExecutionResult, reference_configuration.execution_result).runtime, cast(ExecutionResult, reference_configuration.execution_result).return_code, + cast(ExecutionResult, reference_configuration.execution_result).result_valid, reference_configuration.root_path, ) ) @@ -149,6 +150,7 @@ def run(arguments: AutotunerArguments) -> None: current_config, cast(ExecutionResult, tmp_config.execution_result).runtime, cast(ExecutionResult, tmp_config.execution_result).return_code, + cast(ExecutionResult, tmp_config.execution_result).result_valid, tmp_config.root_path, ) ) @@ -231,10 +233,20 @@ def run(arguments: AutotunerArguments) -> None: # show debug stats stats_str = "Configuration measurements:\n" - stats_str += "[time]\t[applied suggestions]\t[return code]\t[path]\n" - for stats in sorted(debug_stats, key=lambda x: x[1], reverse=True): + stats_str += "[time]\t[applied suggestions]\t[return code]\t[result valid]\t[path]\n" + for stats in sorted(debug_stats, key=lambda x: (x[1]), reverse=True): stats_str += ( - str(round(stats[1], 3)) + "s" + "\t" + str(stats[0]) + "\t" + str(stats[2]) + "\t" + str(stats[3]) + "\n" + str(round(stats[1], 3)) + + "s" + + "\t" + + str(stats[0]) + + "\t" + + str(stats[2]) + + "\t" + + str(stats[3]) + + "\t" + + str(stats[4]) + + "\n" ) logger.info(stats_str) @@ -255,6 +267,8 @@ def run(arguments: AutotunerArguments) -> None: for stats in sorted(debug_stats, key=lambda x: x[1], reverse=False): if str(stats[2]) != "0": continue + if stats[3] == False: # skip invalid results + continue f.write(str(stats[0]) + "; " + str(round(stats[1], 3)) + "; " + str(stats[2]) + ";" + "\n") break From 43b33dc9236841449bd956259a8144ea399b7649 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Mon, 26 Aug 2024 15:17:03 +0200 Subject: [PATCH 090/105] fix(autotuner): filtering of relevant loops --- discopop_library/EmpiricalAutotuning/Autotuner.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/discopop_library/EmpiricalAutotuning/Autotuner.py b/discopop_library/EmpiricalAutotuning/Autotuner.py index 79f05e69c..60f73752a 100644 --- a/discopop_library/EmpiricalAutotuning/Autotuner.py +++ b/discopop_library/EmpiricalAutotuning/Autotuner.py @@ -74,6 +74,16 @@ def run(arguments: AutotunerArguments) -> None: detection_result: DetectionResult = jsonpickle.decode(tmp_str) logger.debug("loaded suggestions") + # get metadata: highest average runtime in hotspot information. Used to filter relevant loops (1% runtime contribution) + max_avg_runtime = 0.0 + for hotspot_type in [HotspotType.YES, HotspotType.MAYBE, HotspotType.NO]: + if hotspot_information: + if hotspot_type not in hotspot_information: + continue + for info in hotspot_information[hotspot_type]: + if info[4] > max_avg_runtime: + max_avg_runtime = info[4] + # greedy search for best suggestion configuration: # for all hotspot types in descending importance: visited_configurations: List[List[SUGGESTION_ID]] = [] @@ -109,9 +119,7 @@ def run(arguments: AutotunerArguments) -> None: + "s" ) # check if the loop contributes more than 1% to the total runtime - loop_contributes_significantly = loop_tuple[4] > ( - cast(ExecutionResult, reference_configuration.execution_result).runtime / 100 - ) + loop_contributes_significantly = loop_tuple[4] > (max_avg_runtime / 100) if not loop_contributes_significantly: statistics_graph.add_child(loop_str, color=NodeColor.ORANGE) else: From e84d9b55364f17dfb72a04e262a5e540cef9c265 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Mon, 26 Aug 2024 14:35:30 +0200 Subject: [PATCH 091/105] fix(explorer)[reduction,doall]: minor fix regarding considered metadata --- discopop_explorer/pattern_detectors/do_all_detector.py | 4 +++- discopop_explorer/pattern_detectors/reduction_detector.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/discopop_explorer/pattern_detectors/do_all_detector.py b/discopop_explorer/pattern_detectors/do_all_detector.py index 00eb620f0..49d1f9245 100644 --- a/discopop_explorer/pattern_detectors/do_all_detector.py +++ b/discopop_explorer/pattern_detectors/do_all_detector.py @@ -319,7 +319,9 @@ def __check_loop_dependencies( ) cond_2 = len([cf for cf in called_functions_lineids if cf in dep.metadata_inter_call_dep]) > 0 cond_3 = len([t for t in parent_loops if t in dep.metadata_inter_iteration_dep]) > 0 - if cond_1 or cond_2 or cond_3: + cond_4 = root_loop.start_position() in dep.metadata_inter_iteration_dep + # if cond_1 or cond_2 or cond_3: + if cond_2 or cond_4: return True # if it is an intra iteration dependency, it is problematic if it belongs to a parent loop else: diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index 21d8960b1..88ef8620e 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -284,7 +284,9 @@ def __check_loop_dependencies( ) cond_2 = len([cf for cf in called_functions_lineids if cf in dep.metadata_inter_call_dep]) > 0 cond_3 = len([t for t in parent_loops if t in dep.metadata_inter_iteration_dep]) > 0 - if cond_1 or cond_2 or cond_3: + cond_4 = root_loop.start_position() in dep.metadata_inter_iteration_dep + # if cond_1 or cond_2 or cond_3: + if cond_2 or cond_4: return True elif dep.dtype == DepType.WAR: # check WAR dependencies From 2a788f2506c732f5e4dd81cc7c5c110ce7ffcf3e Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Mon, 26 Aug 2024 17:10:27 +0200 Subject: [PATCH 092/105] fix(instrumentation): stability improvement, allow invoke instructions --- DiscoPoP/static_analysis/createCUs.cpp | 2 +- scripts/CMakeLists.txt | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/DiscoPoP/static_analysis/createCUs.cpp b/DiscoPoP/static_analysis/createCUs.cpp index fcf09a27d..60904c965 100644 --- a/DiscoPoP/static_analysis/createCUs.cpp +++ b/DiscoPoP/static_analysis/createCUs.cpp @@ -322,7 +322,7 @@ void DiscoPoP::createCUs(Region *TopRegion, set &globalVariablesSet, vec } } else // get name of the indirect function which is called { - Value *v = (cast(instruction))->getCalledOperand(); + Value* v = (cast(instruction))->getCalledOperand(); Value *sv = v->stripPointerCasts(); n->name = sv->getName().str(); } diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index badd18b39..f0f49f6da 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -21,12 +21,15 @@ configure_file(MPI_LINKER_wrapper.sh MPI_LINKER_wrapper.sh COPYONLY) # create symlinks to files set(DP_LOCAL_BIN_DIR "$ENV{HOME}/.local/bin") if(EXISTS ${DP_LOCAL_BIN_DIR}) + execute_process(COMMAND rm -f ${DP_LOCAL_BIN_DIR}/discopop_cc) message(STATUS "Creating symlink ${DP_LOCAL_BIN_DIR}/discopop_cc to ${CMAKE_CURRENT_BINARY_DIR}/CC_wrapper.sh") execute_process(COMMAND ln -sf ${CMAKE_CURRENT_BINARY_DIR}/CC_wrapper.sh ${DP_LOCAL_BIN_DIR}/discopop_cc) + execute_process(COMMAND rm -f ${DP_LOCAL_BIN_DIR}/discopop_cxx) message(STATUS "Creating symlink ${DP_LOCAL_BIN_DIR}/discopop_cxx to ${CMAKE_CURRENT_BINARY_DIR}/CXX_wrapper.sh") execute_process(COMMAND ln -sf ${CMAKE_CURRENT_BINARY_DIR}/CXX_wrapper.sh ${DP_LOCAL_BIN_DIR}/discopop_cxx) + execute_process(COMMAND rm -f ${DP_LOCAL_BIN_DIR}/discopop_cmake) message(STATUS "Creating symlink ${DP_LOCAL_BIN_DIR}/discopop_cmake to ${CMAKE_CURRENT_BINARY_DIR}/CMAKE_wrapper.sh") execute_process(COMMAND ln -sf ${CMAKE_CURRENT_BINARY_DIR}/CMAKE_wrapper.sh ${DP_LOCAL_BIN_DIR}/discopop_cmake) else() From 328a60dfbf8907580c733faad8bfd1b89de1fc45 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Tue, 27 Aug 2024 10:42:13 +0200 Subject: [PATCH 093/105] fix: potential endless recursion in hybrid instrumentation --- DiscoPoP/hybrid_analysis/InstructionCFG.cpp | 24 +++++++++++++++------ DiscoPoP/hybrid_analysis/InstructionCFG.hpp | 2 +- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/DiscoPoP/hybrid_analysis/InstructionCFG.cpp b/DiscoPoP/hybrid_analysis/InstructionCFG.cpp index 035c2545a..09cabbe18 100644 --- a/DiscoPoP/hybrid_analysis/InstructionCFG.cpp +++ b/DiscoPoP/hybrid_analysis/InstructionCFG.cpp @@ -30,10 +30,11 @@ InstructionCFG::InstructionCFG(dputil::VariableNameFinder *_VNF, Function &F) : } // Add edges from last instruction in current block to first instruction all // the successor blocks - if (previousInstruction != nullptr) - findAndAddFirstRelevantInstructionInSuccessorBlocks(&BB, previousInstruction); + if (previousInstruction != nullptr){ + std::set> visited; + findAndAddFirstRelevantInstructionInSuccessorBlocks(&BB, previousInstruction, &visited); + } } - // Conect entry/exit nodes for (auto instNode : Graph::getInstructionNodes()) { if (instNode != entry && instNode != exit) { @@ -47,7 +48,17 @@ InstructionCFG::InstructionCFG(dputil::VariableNameFinder *_VNF, Function &F) : } void InstructionCFG::findAndAddFirstRelevantInstructionInSuccessorBlocks(BasicBlock *BB, - Instruction *previousInstruction) { + Instruction *previousInstruction, + std::set> *visited) { + // Check for and break out of cycles + std::pair tmp_pair = std::make_pair(BB, previousInstruction); + const bool already_visited = visited->find(tmp_pair) != visited->end(); + if(already_visited){ + return; + } + // register visited node + visited->insert(tmp_pair); + bool hasSuccessors = false; for (BasicBlock *S : successors(BB)) { hasSuccessors = true; @@ -62,8 +73,9 @@ void InstructionCFG::findAndAddFirstRelevantInstructionInSuccessorBlocks(BasicBl Graph::addEdge(Graph::getInstructionNode(previousInstruction), exit); } } - if (S != BB) - findAndAddFirstRelevantInstructionInSuccessorBlocks(S, previousInstruction); + if (S != BB){ + findAndAddFirstRelevantInstructionInSuccessorBlocks(S, previousInstruction, visited); + } next:; } } diff --git a/DiscoPoP/hybrid_analysis/InstructionCFG.hpp b/DiscoPoP/hybrid_analysis/InstructionCFG.hpp index daee2db4e..634644214 100644 --- a/DiscoPoP/hybrid_analysis/InstructionCFG.hpp +++ b/DiscoPoP/hybrid_analysis/InstructionCFG.hpp @@ -33,7 +33,7 @@ class InstructionCFG : public Graph { dputil::VariableNameFinder *VNF; set highlightedInstructionNodes; - void findAndAddFirstRelevantInstructionInSuccessorBlocks(BasicBlock *BB, Instruction *previousInstruction); + void findAndAddFirstRelevantInstructionInSuccessorBlocks(BasicBlock *BB, Instruction *previousInstruction, std::set> *visited); public: InstructionCFG(dputil::VariableNameFinder *_VNF, Function &F); From 781a66c23de478ddd32d62c4711e93dc95d553b4 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Mon, 14 Oct 2024 16:20:47 +0200 Subject: [PATCH 094/105] fix(autotuner): minor --- discopop_library/EmpiricalAutotuning/Autotuner.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/discopop_library/EmpiricalAutotuning/Autotuner.py b/discopop_library/EmpiricalAutotuning/Autotuner.py index 60f73752a..a906d120b 100644 --- a/discopop_library/EmpiricalAutotuning/Autotuner.py +++ b/discopop_library/EmpiricalAutotuning/Autotuner.py @@ -118,8 +118,8 @@ def run(arguments: AutotunerArguments) -> None: + str(round(loop_tuple[4], 3)) + "s" ) - # check if the loop contributes more than 1% to the total runtime - loop_contributes_significantly = loop_tuple[4] > (max_avg_runtime / 100) + # check if the loop contributes more than 1% to the total runtime, if hotspot information exists + loop_contributes_significantly = (loop_tuple[4] > (max_avg_runtime / 100)) or not hotspot_information if not loop_contributes_significantly: statistics_graph.add_child(loop_str, color=NodeColor.ORANGE) else: From 1bcc70b5aa8d097fa740a12adee0485e1b21a4ad Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Thu, 17 Oct 2024 13:40:26 +0200 Subject: [PATCH 095/105] feat(profiler)[statistics]: profiling time --- DiscoPoP/llvm_hooks/doInitialization.cpp | 7 +++++++ rtlib/injected_functions/dp_finalize.cpp | 18 ++++++++++++++++++ rtlib/injected_functions/dp_func_entry.cpp | 2 ++ rtlib/runtimeFunctionsGlobals.cpp | 3 +++ rtlib/runtimeFunctionsGlobals.hpp | 4 ++++ 5 files changed, 34 insertions(+) diff --git a/DiscoPoP/llvm_hooks/doInitialization.cpp b/DiscoPoP/llvm_hooks/doInitialization.cpp index 64a648d94..00295c6df 100644 --- a/DiscoPoP/llvm_hooks/doInitialization.cpp +++ b/DiscoPoP/llvm_hooks/doInitialization.cpp @@ -36,6 +36,13 @@ bool DiscoPoP::doInitialization(Module &M) { if (stat(getenv("DOT_DISCOPOP_PROFILER"), &st2) == -1) { mkdir(getenv("DOT_DISCOPOP_PROFILER"), 0777); } + // prepare statistics directory if not present + struct stat st3 = {0}; + std::string tmp_str_2(getenv("DOT_DISCOPOP_PROFILER")); + tmp_str_2 += "/statistics"; + if (stat(tmp_str_2.data(), &st3) == -1) { + mkdir(tmp_str_2.data(), 0777); + } // prepare target directory if not present char const *tmp2 = getenv("DP_PROJECT_ROOT_DIR"); diff --git a/rtlib/injected_functions/dp_finalize.cpp b/rtlib/injected_functions/dp_finalize.cpp index b05fec996..1ca9bd124 100644 --- a/rtlib/injected_functions/dp_finalize.cpp +++ b/rtlib/injected_functions/dp_finalize.cpp @@ -25,6 +25,7 @@ #include #include #include +#include using namespace std; @@ -189,6 +190,23 @@ void __dp_finalize(LID lid) { delete out; + // output elapsed time for profiling + std::chrono::milliseconds time_elapsed = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - statistics_profiling_start_time); +#ifdef __linux__ + // try to get an output file name w.r.t. the target application + // if it is not available, fall back to "Output.txt" + char *selfPath = new char[PATH_MAX]; + if (selfPath != nullptr) { + std::string tmp2(getenv("DOT_DISCOPOP_PROFILER")); + tmp2 += "/statistics/profiling_time.txt"; + std::ofstream stats_file; + stats_file.open(tmp2.data(), ios::out); + stats_file << std::to_string(time_elapsed.count()) << " ms\n"; + stats_file.flush(); + stats_file.close(); + } +#endif + dpInited = false; targetTerminated = true; // mark the target program has returned from main() diff --git a/rtlib/injected_functions/dp_func_entry.cpp b/rtlib/injected_functions/dp_func_entry.cpp index 0691507a6..a4f4013e9 100644 --- a/rtlib/injected_functions/dp_func_entry.cpp +++ b/rtlib/injected_functions/dp_func_entry.cpp @@ -25,6 +25,7 @@ #include #include #include +#include using namespace std; @@ -52,6 +53,7 @@ void __dp_func_entry(LID lid, int32_t isStart) { // This part should be executed only once. readRuntimeInfo(); timers = new Timers(); + statistics_profiling_start_time = std::chrono::high_resolution_clock::now(); #ifdef DP_INTERNAL_TIMER const auto timer = Timer(timers, TimerRegion::FUNC_ENTRY); #endif diff --git a/rtlib/runtimeFunctionsGlobals.cpp b/rtlib/runtimeFunctionsGlobals.cpp index a8a8f10d5..5ea2b3bb3 100644 --- a/rtlib/runtimeFunctionsGlobals.cpp +++ b/rtlib/runtimeFunctionsGlobals.cpp @@ -86,6 +86,9 @@ bool stop = false; // ONLY set stop to true if no more // be collected thread_local depMap *myMap = nullptr; +// statistics +std::chrono::high_resolution_clock::time_point statistics_profiling_start_time; + /******* END: parallelization section *******/ } // namespace __dp diff --git a/rtlib/runtimeFunctionsGlobals.hpp b/rtlib/runtimeFunctionsGlobals.hpp index 0da5fc242..4ca5c4b92 100644 --- a/rtlib/runtimeFunctionsGlobals.hpp +++ b/rtlib/runtimeFunctionsGlobals.hpp @@ -30,6 +30,7 @@ #include #include #include +#include extern bool USE_PERFECT; @@ -98,4 +99,7 @@ extern bool stop; // ONLY set stop to true if no more accessed // be collected extern thread_local depMap *myMap; +// statistics +extern std::chrono::high_resolution_clock::time_point statistics_profiling_start_time; + } // namespace __dp From c4a88342d6a424558abcf3f21dab5cf14dc77b7e Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 23 Oct 2024 09:53:32 +0200 Subject: [PATCH 096/105] feat(explorer): calculate code statistics --- discopop_explorer/__main__.py | 4 + discopop_explorer/discopop_explorer.py | 6 + .../statistics/collect_statistics.py | 125 +++++++++ .../cyclomatic_complexity/boxplot.py | 63 +++++ .../cyclomatic_complexity/cc_dictionary.py | 60 ++++ .../cyclomatic_complexity/subtree.py | 52 ++++ .../statistics/cyclomatic_complexity/total.py | 32 +++ .../statistics/maximum_call_path_depth.py | 21 ++ .../statistics/num_function_calls.py | 24 ++ .../utilities/statistics/output_statistics.py | 259 ++++++++++++++++++ .../statistics/suggestion_call_path_depths.py | 23 ++ .../suggestion_cyclomatic_complexity.py | 39 +++ .../statistics/suggestion_lines_of_code.py | 56 ++++ .../statistics/utilities/call_path_depth.py | 39 +++ .../utilities/num_function_calls.py | 34 +++ 15 files changed, 837 insertions(+) create mode 100644 discopop_explorer/utilities/statistics/collect_statistics.py create mode 100644 discopop_explorer/utilities/statistics/cyclomatic_complexity/boxplot.py create mode 100644 discopop_explorer/utilities/statistics/cyclomatic_complexity/cc_dictionary.py create mode 100644 discopop_explorer/utilities/statistics/cyclomatic_complexity/subtree.py create mode 100644 discopop_explorer/utilities/statistics/cyclomatic_complexity/total.py create mode 100644 discopop_explorer/utilities/statistics/maximum_call_path_depth.py create mode 100644 discopop_explorer/utilities/statistics/num_function_calls.py create mode 100644 discopop_explorer/utilities/statistics/output_statistics.py create mode 100644 discopop_explorer/utilities/statistics/suggestion_call_path_depths.py create mode 100644 discopop_explorer/utilities/statistics/suggestion_cyclomatic_complexity.py create mode 100644 discopop_explorer/utilities/statistics/suggestion_lines_of_code.py create mode 100644 discopop_explorer/utilities/statistics/utilities/call_path_depth.py create mode 100644 discopop_explorer/utilities/statistics/utilities/num_function_calls.py diff --git a/discopop_explorer/__main__.py b/discopop_explorer/__main__.py index dd523cbf4..b0dee494c 100644 --- a/discopop_explorer/__main__.py +++ b/discopop_explorer/__main__.py @@ -104,6 +104,9 @@ def parse_args() -> ExplorerArguments: "--llvm-cxxfilt-path", type=str, default=None, help="Path to llvm-cxxfilt executable. Required for task pattern detector if non-standard path should be used.", ) + experimental_parser.add_argument( + "--disable-statistics", action="store_false", help="Disable the calculation and storing of statistics for code and generated suggestions." + ) # fmt: on arguments = parser.parse_args() @@ -156,6 +159,7 @@ def parse_args() -> ExplorerArguments: log_level=arguments.log.upper(), write_log=arguments.write_log, load_existing_doall_and_reduction_patterns=arguments.load_existing_doall_and_reduction_patterns, + collect_statistics=arguments.disable_statistics, ) diff --git a/discopop_explorer/discopop_explorer.py b/discopop_explorer/discopop_explorer.py index d9fd4aa0a..b5cb51895 100644 --- a/discopop_explorer/discopop_explorer.py +++ b/discopop_explorer/discopop_explorer.py @@ -19,6 +19,7 @@ import pstats2 # type:ignore from pluginbase import PluginBase # type: ignore from discopop_explorer.functions.PEGraph.output.json import dump_to_pickled_json +from discopop_explorer.utilities.statistics.collect_statistics import collect_statistics from discopop_library.ArgumentClasses.GeneralArguments import GeneralArguments # type: ignore from discopop_library.HostpotLoader.HotspotLoaderArguments import HotspotLoaderArguments from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType @@ -65,6 +66,7 @@ class ExplorerArguments(GeneralArguments): llvm_cxxfilt_path: Optional[str] microbench_file: Optional[str] load_existing_doall_and_reduction_patterns: bool + collect_statistics: bool def __post_init__(self) -> None: self.__validate() @@ -245,6 +247,10 @@ def run(arguments: ExplorerArguments) -> None: end = time.time() + # collect code and suggestions statistics, if requested + if arguments.collect_statistics: + collect_statistics(arguments, res) + if arguments.enable_pet_dump_file is not None: with open(arguments.enable_pet_dump_file, "w+") as f: f.write(dump_to_pickled_json(res.pet)) diff --git a/discopop_explorer/utilities/statistics/collect_statistics.py b/discopop_explorer/utilities/statistics/collect_statistics.py new file mode 100644 index 000000000..5c2ac560d --- /dev/null +++ b/discopop_explorer/utilities/statistics/collect_statistics.py @@ -0,0 +1,125 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from __future__ import annotations +from typing import TYPE_CHECKING +import logging + +from discopop_explorer.utilities.statistics.cyclomatic_complexity.boxplot import get_cyclomatic_complexities_for_boxplot +from discopop_explorer.utilities.statistics.cyclomatic_complexity.total import get_summed_cyclomatic_complexity +from discopop_explorer.utilities.statistics.maximum_call_path_depth import get_maximum_call_path_depth +from discopop_explorer.utilities.statistics.num_function_calls import get_suggestion_num_function_calls +from discopop_explorer.utilities.statistics.output_statistics import ( + output_aggregated_suggestion_statistics, + output_code_statistics, + output_suggestion_statistics, +) +from discopop_explorer.utilities.statistics.suggestion_call_path_depths import get_suggestion_call_path_depths +from discopop_explorer.utilities.statistics.suggestion_cyclomatic_complexity import ( + get_suggestion_summed_cyclomatic_complexity_from_calls, +) +from discopop_explorer.utilities.statistics.suggestion_lines_of_code import ( + get_suggestion_immediate_lines_of_code, + get_suggestion_lines_of_code_including_calls, +) + +if TYPE_CHECKING: + from discopop_explorer.discopop_explorer import ExplorerArguments + from discopop_library.result_classes.DetectionResult import DetectionResult + +logger = logging.getLogger("statistics") + + +def collect_statistics(arguments: ExplorerArguments, res: DetectionResult) -> None: + logger.info("Collecting code statistics...") + maximum_call_path_depth = get_maximum_call_path_depth(res.pet) + logger.debug("--> maximum_call_path_depth: " + str(maximum_call_path_depth)) + suggestion_call_path_depths = get_suggestion_call_path_depths(res) + logger.debug( + "--> suggestion_call_path_depths: " + + str([str(key) + " => " + str(suggestion_call_path_depths[key]) for key in suggestion_call_path_depths]) + ) + suggestion_num_function_calls = get_suggestion_num_function_calls(res) + logger.debug( + "--> suggestion_num_function_calls: " + + str([str(key) + " => " + str(suggestion_num_function_calls[key]) for key in suggestion_num_function_calls]) + ) + suggestion_immediate_lines_of_code = get_suggestion_immediate_lines_of_code(res) + logger.debug( + "--> suggestion_immediate_lines_of_code: " + + str( + [ + str(key) + " => " + str(suggestion_immediate_lines_of_code[key]) + for key in suggestion_immediate_lines_of_code + ] + ) + ) + + suggestion_lines_of_code_including_calls = get_suggestion_lines_of_code_including_calls(res) + logger.debug( + "--> suggestion_lines_of_code_including_calls: " + + str( + [ + str(key) + " => " + str(suggestion_lines_of_code_including_calls[key]) + for key in suggestion_lines_of_code_including_calls + ] + ) + ) + + summed_cyclomatic_complexity = get_summed_cyclomatic_complexity(arguments, res) + logger.debug("--> summed_cyclomatic_complexity = " + str(summed_cyclomatic_complexity)) + + cc_min, cc_max, cc_avg, cc_lower_quart, cc_upper_quart = get_cyclomatic_complexities_for_boxplot(arguments, res) + logger.debug("--> cc_min: " + str(cc_min)) + logger.debug("--> cc_max: " + str(cc_max)) + logger.debug("--> cc_avg: " + str(cc_avg)) + logger.debug("--> cc_lower_quart: " + str(cc_lower_quart)) + logger.debug("--> cc_upper_quart: " + str(cc_upper_quart)) + + suggestion_summed_cyclomatic_complexity_from_calls = get_suggestion_summed_cyclomatic_complexity_from_calls( + arguments, res + ) + logger.debug( + "--> suggestion_summed_cyclomatic_complexity_from_calls: " + + str( + [ + str(key) + " => " + str(suggestion_summed_cyclomatic_complexity_from_calls[key]) + for key in suggestion_summed_cyclomatic_complexity_from_calls + ] + ) + ) + + # output statistics to file + output_code_statistics( + arguments, + maximum_call_path_depth, + summed_cyclomatic_complexity, + cc_min, + cc_max, + cc_avg, + cc_lower_quart, + cc_upper_quart, + ) + + output_suggestion_statistics( + arguments, + suggestion_call_path_depths, + suggestion_num_function_calls, + suggestion_immediate_lines_of_code, + suggestion_lines_of_code_including_calls, + suggestion_summed_cyclomatic_complexity_from_calls, + ) + + output_aggregated_suggestion_statistics( + arguments, + suggestion_call_path_depths, + suggestion_num_function_calls, + suggestion_immediate_lines_of_code, + suggestion_lines_of_code_including_calls, + suggestion_summed_cyclomatic_complexity_from_calls, + ) diff --git a/discopop_explorer/utilities/statistics/cyclomatic_complexity/boxplot.py b/discopop_explorer/utilities/statistics/cyclomatic_complexity/boxplot.py new file mode 100644 index 000000000..20e6b26e4 --- /dev/null +++ b/discopop_explorer/utilities/statistics/cyclomatic_complexity/boxplot.py @@ -0,0 +1,63 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from __future__ import annotations +from typing import TYPE_CHECKING, Dict, List, Tuple + +if TYPE_CHECKING: + from discopop_explorer.discopop_explorer import ExplorerArguments + from discopop_library.result_classes.DetectionResult import DetectionResult + +# define aliases for readability +from subprocess import check_output +from discopop_library.PathManagement.PathManagement import load_file_mapping + + +MIN = int +MAX = int +AVG = int +LOWER_QUART = int +UPPER_QUART = int + + +def get_cyclomatic_complexities_for_boxplot( + arguments: ExplorerArguments, res: DetectionResult +) -> Tuple[MIN, MAX, AVG, LOWER_QUART, UPPER_QUART]: + file_mapping = load_file_mapping(arguments.file_mapping_file) + # get summed cyclomatic complexity for all functions in all files + cmd = ["pmccabe", "-C"] + for file_id in file_mapping: + file_path = file_mapping[file_id] + cmd.append(str(file_path)) + out = check_output(cmd).decode("utf-8") + + # unpack and store results temporarily + cyclomatic_complexities: List[int] = [] + for line in out.split("\n"): + split_line = line.split("\t") + if len(split_line) < 9: + continue + cyclomatic_complexity = split_line[1] + # file_path = split_line[7] + # function_name = split_line[8] + + cyclomatic_complexities.append(int(cyclomatic_complexity)) + + # calculate statistics + cc_min: MIN = min(cyclomatic_complexities) + cc_max: MAX = max(cyclomatic_complexities) + cc_avg: AVG = int(sum(cyclomatic_complexities) / len(cyclomatic_complexities)) + sorted_cyclomatic_complexities = sorted(cyclomatic_complexities) + lower_quartile_idx = int((len(sorted_cyclomatic_complexities) + 1) * 1 / 4) + upper_quartile_idx = int((len(sorted_cyclomatic_complexities) + 1) * 3 / 4) + lower_quartile = sorted_cyclomatic_complexities[lower_quartile_idx] + if len(sorted_cyclomatic_complexities) == 1: + upper_quartile_idx = 0 + upper_quartile = sorted_cyclomatic_complexities[upper_quartile_idx] + + return cc_min, cc_max, cc_avg, lower_quartile, upper_quartile diff --git a/discopop_explorer/utilities/statistics/cyclomatic_complexity/cc_dictionary.py b/discopop_explorer/utilities/statistics/cyclomatic_complexity/cc_dictionary.py new file mode 100644 index 000000000..dbcbb280d --- /dev/null +++ b/discopop_explorer/utilities/statistics/cyclomatic_complexity/cc_dictionary.py @@ -0,0 +1,60 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from __future__ import annotations +from subprocess import check_output +from typing import TYPE_CHECKING, Dict, Optional + +from discopop_library.PathManagement.PathManagement import load_file_mapping + +if TYPE_CHECKING: + from discopop_explorer.discopop_explorer import ExplorerArguments + from discopop_library.result_classes.DetectionResult import DetectionResult + + +FILE_ID = int +FILEPATH = str +FUNC_NAME = str +CYC_COMP = int + +CC_DICT = Dict[FILE_ID, Dict[FUNC_NAME, CYC_COMP]] + + +def get_cyclomatic_complexity_dictionary(arguments: ExplorerArguments, res: DetectionResult) -> CC_DICT: + file_mapping = load_file_mapping(arguments.file_mapping_file) + # get summed cyclomatic complexity for all functions in all files + cmd = ["pmccabe", "-C"] + for file_id in file_mapping: + file_path = file_mapping[file_id] + cmd.append(str(file_path)) + out = check_output(cmd).decode("utf-8") + + # unpack and repack results + cc_dict: Dict[FILE_ID, Dict[FUNC_NAME, CYC_COMP]] = dict() + for line in out.split("\n"): + split_line = line.split("\t") + if len(split_line) < 9: + continue + cyclomatic_complexity: CYC_COMP = int(split_line[1]) + file_path_2: FILEPATH = split_line[7] + # get file_id + file_id_2: Optional[int] = None + for file_id in file_mapping: + if str(file_mapping[file_id]) == file_path_2: + file_id_2 = file_id + + if file_id_2 is None: + continue + + func_name: FUNC_NAME = split_line[8] + + if file_id_2 not in cc_dict: + cc_dict[file_id_2] = dict() + cc_dict[file_id_2][func_name] = cyclomatic_complexity + + return cc_dict diff --git a/discopop_explorer/utilities/statistics/cyclomatic_complexity/subtree.py b/discopop_explorer/utilities/statistics/cyclomatic_complexity/subtree.py new file mode 100644 index 000000000..06266274e --- /dev/null +++ b/discopop_explorer/utilities/statistics/cyclomatic_complexity/subtree.py @@ -0,0 +1,52 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from __future__ import annotations + +from typing import TYPE_CHECKING, List, cast + +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.queries.edges import out_edges + +if TYPE_CHECKING: + from discopop_explorer.discopop_explorer import ExplorerArguments + from discopop_library.result_classes.DetectionResult import DetectionResult + from discopop_explorer.utilities.statistics.cyclomatic_complexity.cc_dictionary import CC_DICT + from discopop_explorer.aliases.NodeID import NodeID + +from discopop_explorer.classes.PEGraph.FunctionNode import FunctionNode +from discopop_explorer.functions.PEGraph.queries.subtree import subtree_of_type + + +def get_subtree_cyclomatic_complexity_from_calls( + arguments: ExplorerArguments, res: DetectionResult, cc_dict: CC_DICT, root_node_id: NodeID +) -> int: + subtree = subtree_of_type(res.pet, res.pet.node_at(root_node_id)) + # collect called functions + called_functions: List[FunctionNode] = [] + for node in subtree: + out_call_edges = out_edges(res.pet, node.id, EdgeType.CALLSNODE) + for _, target, _ in out_call_edges: + called_functions.append(cast(FunctionNode, res.pet.node_at(target))) + # identify cyclomatic complexities for called functions by matching against cc_dict entries + # due to overloading or name extensions (i.e. get_a vs. get_a_and_b), select the shortest function name that matches + cyclomatic_complexities: List[int] = [] + for func in called_functions: + if func.file_id not in cc_dict: + continue + candidates: List[str] = [] + for clean_func_name in cc_dict[func.file_id]: + if clean_func_name in func.name: + candidates.append(clean_func_name) + sorted_candidates = sorted(candidates, key=lambda x: len(x)) + if len(sorted_candidates) > 0: + best_match = sorted_candidates[0] + cyclomatic_complexities.append(cc_dict[func.file_id][best_match]) + + # sum cyclomatic complexities of called functions + return sum(cyclomatic_complexities) diff --git a/discopop_explorer/utilities/statistics/cyclomatic_complexity/total.py b/discopop_explorer/utilities/statistics/cyclomatic_complexity/total.py new file mode 100644 index 000000000..6cb660eb5 --- /dev/null +++ b/discopop_explorer/utilities/statistics/cyclomatic_complexity/total.py @@ -0,0 +1,32 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from __future__ import annotations +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from discopop_explorer.discopop_explorer import ExplorerArguments + from discopop_library.result_classes.DetectionResult import DetectionResult +from discopop_library.PathManagement.PathManagement import load_file_mapping + + +from subprocess import check_output + + +def get_summed_cyclomatic_complexity(arguments: ExplorerArguments, res: DetectionResult) -> int: + """calculate the total cyclomatic complexity""" + file_mapping = load_file_mapping(arguments.file_mapping_file) + # get summed cyclomatic complexity for all functions in all files + cmd = ["pmccabe", "-T"] + for file_id in file_mapping: + file_path = file_mapping[file_id] + cmd.append(str(file_path)) + out = check_output(cmd).decode("utf-8") + summed_cyclomatic_complexity = int(out.split("\t")[1]) + + return summed_cyclomatic_complexity diff --git a/discopop_explorer/utilities/statistics/maximum_call_path_depth.py b/discopop_explorer/utilities/statistics/maximum_call_path_depth.py new file mode 100644 index 000000000..b92e66f0b --- /dev/null +++ b/discopop_explorer/utilities/statistics/maximum_call_path_depth.py @@ -0,0 +1,21 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX +from discopop_explorer.enums.NodeType import NodeType +from discopop_explorer.functions.PEGraph.queries.nodes import all_nodes +from discopop_explorer.utilities.statistics.utilities.call_path_depth import get_outgoing_call_path_depth + + +def get_maximum_call_path_depth(pet: PEGraphX) -> int: + res = 0 + for node in all_nodes(pet): + if node.type != NodeType.FUNC: + continue + res = max(res, get_outgoing_call_path_depth(pet, node)) + return res diff --git a/discopop_explorer/utilities/statistics/num_function_calls.py b/discopop_explorer/utilities/statistics/num_function_calls.py new file mode 100644 index 000000000..fab988915 --- /dev/null +++ b/discopop_explorer/utilities/statistics/num_function_calls.py @@ -0,0 +1,24 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + + +from typing import Dict, Set +from discopop_explorer.aliases.NodeID import NodeID +from discopop_explorer.utilities.statistics.utilities.num_function_calls import get_num_function_calls +from discopop_library.result_classes.DetectionResult import DetectionResult + + +def get_suggestion_num_function_calls(res: DetectionResult) -> Dict[int, int]: + res_dict: Dict[int, int] = dict() + + # collect number of function calls in entire subtree of a parallelization suggestion + for pattern_type in res.patterns.__dict__: + for pattern in res.patterns.__dict__[pattern_type]: + res_dict[pattern.pattern_id] = get_num_function_calls(res.pet, res.pet.node_at(pattern.node_id), []) + + return res_dict diff --git a/discopop_explorer/utilities/statistics/output_statistics.py b/discopop_explorer/utilities/statistics/output_statistics.py new file mode 100644 index 000000000..a0e7c4f49 --- /dev/null +++ b/discopop_explorer/utilities/statistics/output_statistics.py @@ -0,0 +1,259 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from __future__ import annotations +import json +import os +from typing import TYPE_CHECKING, Dict, List + +from discopop_explorer.aliases.NodeID import NodeID + +if TYPE_CHECKING: + from discopop_explorer.discopop_explorer import ExplorerArguments + + +def output_code_statistics( + arguments: ExplorerArguments, + maximum_call_path_depth: int, + summed_cyclomatic_complexity: int, + cc_min: int, + cc_max: int, + cc_avg: int, + cc_lower_quart: int, + cc_upper_quart: int, +) -> None: + # create statistics directory + if not os.path.exists(os.path.join(arguments.project_path, "explorer", "statistics")): + os.mkdir(os.path.join(arguments.project_path, "explorer", "statistics")) + # clear existing result + statistics_file = os.path.join(arguments.project_path, "explorer", "statistics", "code_statistics.json") + if os.path.exists(statistics_file): + os.remove(statistics_file) + + statistics_dict: Dict[str, int] = dict() + statistics_dict["maximum_call_path_depth"] = maximum_call_path_depth + statistics_dict["summed_cyclomatic_complexity"] = summed_cyclomatic_complexity + statistics_dict["cc_min"] = cc_min + statistics_dict["cc_max"] = cc_max + statistics_dict["cc_avg"] = cc_avg + statistics_dict["cc_lower_quart"] = cc_lower_quart + statistics_dict["cc_upper_quart"] = cc_upper_quart + + with open(statistics_file, "w+") as f: + f.write(json.dumps(statistics_dict) + "\n") + + +def output_suggestion_statistics( + arguments: ExplorerArguments, + suggestion_call_path_depths: Dict[int, int], + suggestion_num_function_calls: Dict[int, int], + suggestion_immediate_lines_of_code: Dict[int, int], + suggestion_lines_of_code_including_calls: Dict[int, int], + suggestion_summed_cyclomatic_complexity_from_calls: Dict[int, int], +) -> None: + # create statistics directory + if not os.path.exists(os.path.join(arguments.project_path, "explorer", "statistics")): + os.mkdir(os.path.join(arguments.project_path, "explorer", "statistics")) + # clear existing result + statistics_file_by_suggestionID = os.path.join( + arguments.project_path, "explorer", "statistics", "suggestion_statistics_by_suggestionID.json" + ) + if os.path.exists(statistics_file_by_suggestionID): + os.remove(statistics_file_by_suggestionID) + + statistics_dict_by_suggestionID: Dict[int, Dict[str, int]] = dict() + + for suggestion_id in suggestion_call_path_depths: + if suggestion_id not in statistics_dict_by_suggestionID: + statistics_dict_by_suggestionID[suggestion_id] = dict() + statistics_dict_by_suggestionID[suggestion_id]["suggestion_call_path_depth"] = suggestion_call_path_depths[ + suggestion_id + ] + + for suggestion_id in suggestion_num_function_calls: + if suggestion_id not in statistics_dict_by_suggestionID: + statistics_dict_by_suggestionID[suggestion_id] = dict() + statistics_dict_by_suggestionID[suggestion_id]["suggestion_num_function_calls"] = suggestion_num_function_calls[ + suggestion_id + ] + + for suggestion_id in suggestion_summed_cyclomatic_complexity_from_calls: + if suggestion_id not in statistics_dict_by_suggestionID: + statistics_dict_by_suggestionID[suggestion_id] = dict() + statistics_dict_by_suggestionID[suggestion_id][ + "suggestion_summed_cyclomatic_complexity_from_calls" + ] = suggestion_summed_cyclomatic_complexity_from_calls[suggestion_id] + + for suggestion_id in suggestion_immediate_lines_of_code: + if suggestion_id not in statistics_dict_by_suggestionID: + statistics_dict_by_suggestionID[suggestion_id] = dict() + statistics_dict_by_suggestionID[suggestion_id][ + "suggestion_immediate_lines_of_code" + ] = suggestion_immediate_lines_of_code[suggestion_id] + + for suggestion_id in suggestion_lines_of_code_including_calls: + if suggestion_id not in statistics_dict_by_suggestionID: + statistics_dict_by_suggestionID[suggestion_id] = dict() + statistics_dict_by_suggestionID[suggestion_id][ + "suggestion_lines_of_code_including_calls" + ] = suggestion_lines_of_code_including_calls[suggestion_id] + + with open(statistics_file_by_suggestionID, "w+") as f: + f.write(json.dumps(statistics_dict_by_suggestionID) + "\n") + + +def output_aggregated_suggestion_statistics( + arguments: ExplorerArguments, + suggestion_call_path_depths: Dict[int, int], + suggestion_num_function_calls: Dict[int, int], + suggestion_immediate_lines_of_code: Dict[int, int], + suggestion_lines_of_code_including_calls: Dict[int, int], + suggestion_summed_cyclomatic_complexity_from_calls: Dict[int, int], +) -> None: + res_dict: Dict[str, Dict[str, int]] = dict() # {value_identifier : {value_descriptor: value}} + # create statistics directory + if not os.path.exists(os.path.join(arguments.project_path, "explorer", "statistics")): + os.mkdir(os.path.join(arguments.project_path, "explorer", "statistics")) + # clear existing result + statistics_file = os.path.join(arguments.project_path, "explorer", "statistics", "suggestion_statistics.json") + if os.path.exists(statistics_file): + os.remove(statistics_file) + + values: List[int] = [] + # suggestion_call_path_depths + values = list(suggestion_call_path_depths.values()) + if len(values) > 0: + v_min = min(values) + v_max = max(values) + v_avg = int(sum(values) / len(values)) + lower_quartile_idx = int((len(values) + 1) * 1 / 4) + upper_quartile_idx = min(len(values) - 1, int((len(values) + 1) * 3 / 4)) + lower_quartile = sorted(values)[lower_quartile_idx] + upper_quartile = sorted(values)[upper_quartile_idx] + else: + v_min = 0 + v_max = 0 + v_avg = 0 + lower_quartile = 0 + upper_quartile = 0 + res_dict["suggestion_call_path_depths"] = { + "min": v_min, + "max": v_max, + "avg": v_avg, + "lower_quartile": lower_quartile, + "upper_quartile": upper_quartile, + } + + # suggestion_num_function_calls + values = list(suggestion_num_function_calls.values()) + if len(values) > 0: + v_min = min(values) + v_max = max(values) + v_avg = int(sum(values) / len(values)) + lower_quartile_idx = int((len(values) + 1) * 1 / 4) + upper_quartile_idx = min(len(values) - 1, int((len(values) + 1) * 3 / 4)) + lower_quartile = sorted(values)[lower_quartile_idx] + upper_quartile = sorted(values)[upper_quartile_idx] + else: + v_min = 0 + v_max = 0 + v_avg = 0 + lower_quartile = 0 + upper_quartile = 0 + res_dict["suggestion_num_function_calls"] = { + "min": v_min, + "max": v_max, + "avg": v_avg, + "lower_quartile": lower_quartile, + "upper_quartile": upper_quartile, + } + + # suggestion_immediate_lines_of_code + values = list(suggestion_immediate_lines_of_code.values()) + if len(values) > 0: + v_min = min(values) + v_max = max(values) + v_avg = int(sum(values) / len(values)) + lower_quartile_idx = int((len(values) + 1) * 1 / 4) + upper_quartile_idx = min(len(values) - 1, int((len(values) + 1) * 3 / 4)) + lower_quartile = sorted(values)[lower_quartile_idx] + upper_quartile = sorted(values)[upper_quartile_idx] + else: + v_min = 0 + v_max = 0 + v_avg = 0 + lower_quartile = 0 + upper_quartile = 0 + res_dict["suggestion_immediate_lines_of_code"] = { + "min": v_min, + "max": v_max, + "avg": v_avg, + "lower_quartile": lower_quartile, + "upper_quartile": upper_quartile, + } + + # suggestion_lines_of_code_including_calls + values = list(suggestion_lines_of_code_including_calls.values()) + if len(values) > 0: + v_min = min(values) + v_max = max(values) + v_avg = int(sum(values) / len(values)) + lower_quartile_idx = int((len(values) + 1) * 1 / 4) + upper_quartile_idx = min(len(values) - 1, int((len(values) + 1) * 3 / 4)) + lower_quartile = sorted(values)[lower_quartile_idx] + upper_quartile = sorted(values)[upper_quartile_idx] + else: + v_min = 0 + v_max = 0 + v_avg = 0 + lower_quartile = 0 + upper_quartile = 0 + res_dict["suggestion_lines_of_code_including_calls"] = { + "min": v_min, + "max": v_max, + "avg": v_avg, + "lower_quartile": lower_quartile, + "upper_quartile": upper_quartile, + } + + # suggestion_summed_cyclomatic_complexity_from_calls + values = list(suggestion_summed_cyclomatic_complexity_from_calls.values()) + if len(values) > 0: + v_min = min(values) + v_max = max(values) + v_avg = int(sum(values) / len(values)) + lower_quartile_idx = int((len(values) + 1) * 1 / 4) + upper_quartile_idx = min(len(values) - 1, int((len(values) + 1) * 3 / 4)) + lower_quartile = sorted(values)[lower_quartile_idx] + upper_quartile = sorted(values)[upper_quartile_idx] + else: + v_min = 0 + v_max = 0 + v_avg = 0 + lower_quartile = 0 + upper_quartile = 0 + res_dict["suggestion_summed_cyclomatic_complexity_from_calls"] = { + "min": v_min, + "max": v_max, + "avg": v_avg, + "lower_quartile": lower_quartile, + "upper_quartile": upper_quartile, + } + + # suggestion_count + suggestion_count = max( + len(suggestion_call_path_depths), + len(suggestion_num_function_calls), + len(suggestion_immediate_lines_of_code), + len(suggestion_lines_of_code_including_calls), + len(suggestion_summed_cyclomatic_complexity_from_calls), + ) + res_dict["suggestion_count"] = {"total": suggestion_count} + + with open(statistics_file, "w+") as f: + f.write(json.dumps(res_dict) + "\n") diff --git a/discopop_explorer/utilities/statistics/suggestion_call_path_depths.py b/discopop_explorer/utilities/statistics/suggestion_call_path_depths.py new file mode 100644 index 000000000..408c362e5 --- /dev/null +++ b/discopop_explorer/utilities/statistics/suggestion_call_path_depths.py @@ -0,0 +1,23 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from typing import Dict, Set +from discopop_explorer.aliases.NodeID import NodeID +from discopop_explorer.utilities.statistics.utilities.call_path_depth import get_outgoing_call_path_depth +from discopop_library.result_classes.DetectionResult import DetectionResult + + +def get_suggestion_call_path_depths(res: DetectionResult) -> Dict[int, int]: + res_dict: Dict[int, int] = dict() + + # collect NodeIDs where suggestions are located + for pattern_type in res.patterns.__dict__: + for pattern in res.patterns.__dict__[pattern_type]: + res_dict[pattern.pattern_id] = get_outgoing_call_path_depth(res.pet, res.pet.node_at(pattern.node_id)) + + return res_dict diff --git a/discopop_explorer/utilities/statistics/suggestion_cyclomatic_complexity.py b/discopop_explorer/utilities/statistics/suggestion_cyclomatic_complexity.py new file mode 100644 index 000000000..853a1e823 --- /dev/null +++ b/discopop_explorer/utilities/statistics/suggestion_cyclomatic_complexity.py @@ -0,0 +1,39 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from __future__ import annotations + +from typing import Dict, TYPE_CHECKING, Set + +from discopop_explorer.utilities.statistics.cyclomatic_complexity.cc_dictionary import ( + get_cyclomatic_complexity_dictionary, +) +from discopop_explorer.utilities.statistics.cyclomatic_complexity.subtree import ( + get_subtree_cyclomatic_complexity_from_calls, +) + +if TYPE_CHECKING: + from discopop_explorer.discopop_explorer import ExplorerArguments + from discopop_library.result_classes.DetectionResult import DetectionResult + from discopop_explorer.aliases.NodeID import NodeID + + +def get_suggestion_summed_cyclomatic_complexity_from_calls( + arguments: ExplorerArguments, res: DetectionResult +) -> Dict[int, int]: + res_dict: Dict[int, int] = dict() + cc_dict = get_cyclomatic_complexity_dictionary(arguments, res) + + # collect NodeIDs where suggestions are located + for pattern_type in res.patterns.__dict__: + for pattern in res.patterns.__dict__[pattern_type]: + res_dict[pattern.pattern_id] = get_subtree_cyclomatic_complexity_from_calls( + arguments, res, cc_dict, pattern.node_id + ) + + return res_dict diff --git a/discopop_explorer/utilities/statistics/suggestion_lines_of_code.py b/discopop_explorer/utilities/statistics/suggestion_lines_of_code.py new file mode 100644 index 000000000..516ffc14e --- /dev/null +++ b/discopop_explorer/utilities/statistics/suggestion_lines_of_code.py @@ -0,0 +1,56 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +from typing import Dict, List, Set +from discopop_explorer.aliases.LineID import LineID +from discopop_explorer.aliases.NodeID import NodeID +from discopop_explorer.functions.PEGraph.queries.subtree import subtree_of_type +from discopop_library.result_classes.DetectionResult import DetectionResult + + +def get_suggestion_immediate_lines_of_code(res: DetectionResult) -> Dict[int, int]: # pattern_id: lines of code + # immediate lines of code --> scope size without following function calls + res_dict: Dict[int, int] = dict() + + # collect scope sizes without following function calls + for pattern_type in res.patterns.__dict__: + for pattern in res.patterns.__dict__[pattern_type]: + start_line_num = int(pattern.start_line.split(":")[1]) + end_line_num = int(pattern.end_line.split(":")[1]) + res_dict[pattern.pattern_id] = end_line_num - start_line_num + + return res_dict + + +def get_suggestion_lines_of_code_including_calls( + res: DetectionResult, +) -> Dict[int, int]: # pattern_id : lines of inlined code + # lines of code are counted as if every function call would be inlined + res_dict: Dict[int, int] = dict() + + # step 1: get immediate lines of code per pattern + for pattern_type in res.patterns.__dict__: + for pattern in res.patterns.__dict__[pattern_type]: + start_line_num = int(pattern.start_line.split(":")[1]) + end_line_num = int(pattern.end_line.split(":")[1]) + res_dict[pattern.pattern_id] = end_line_num - start_line_num + + # step 2: add lines of code from function calls + for pattern_type in res.patterns.__dict__: + for pattern in res.patterns.__dict__[pattern_type]: + pattern_base_node = res.pet.node_at(pattern.node_id) + # get subtree of pattern base node and collect line ids + subtree = subtree_of_type(res.pet, pattern_base_node) + lines_in_subtree: Set[LineID] = set() + for node in subtree: + for line_num_in_scope in range(node.start_line, node.end_line + 1): + lines_in_subtree.add(LineID(str(node.file_id) + ":" + str(line_num_in_scope))) + # count distinct line ids and add to the result + res_dict[pattern.pattern_id] += len(lines_in_subtree) + + return res_dict diff --git a/discopop_explorer/utilities/statistics/utilities/call_path_depth.py b/discopop_explorer/utilities/statistics/utilities/call_path_depth.py new file mode 100644 index 000000000..aca15460a --- /dev/null +++ b/discopop_explorer/utilities/statistics/utilities/call_path_depth.py @@ -0,0 +1,39 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +import copy +from typing import List +from discopop_explorer.classes.PEGraph.Node import Node +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.queries.edges import out_edges +from discopop_explorer.functions.PEGraph.traversal.children import direct_children + + +def get_outgoing_call_path_depth(pet: PEGraphX, node: Node) -> int: + visited: List[Node] = [] + queue: List[tuple[Node, int]] = [(node, 0)] + child_depths: List[int] = [0] + visited.append(node) + + while queue: + cur_node, cur_call_depth = queue.pop() + visited.append(cur_node) + + for child in direct_children(pet, cur_node): + out_call_edges = out_edges(pet, child.id, EdgeType.CALLSNODE) + if len(out_call_edges) > 0: + for _, t, _ in out_call_edges: + if pet.node_at(t) in visited: + continue + child_depths.append(cur_call_depth + 1) + queue.append((pet.node_at(t), cur_call_depth + 1)) + if child not in visited: + queue.append((child, cur_call_depth)) + + return max(child_depths) diff --git a/discopop_explorer/utilities/statistics/utilities/num_function_calls.py b/discopop_explorer/utilities/statistics/utilities/num_function_calls.py new file mode 100644 index 000000000..904b10dc9 --- /dev/null +++ b/discopop_explorer/utilities/statistics/utilities/num_function_calls.py @@ -0,0 +1,34 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + + +import copy +from typing import List, Set +from discopop_explorer.classes.PEGraph.Node import Node +from discopop_explorer.classes.PEGraph.PEGraphX import PEGraphX +from discopop_explorer.enums.EdgeType import EdgeType +from discopop_explorer.functions.PEGraph.queries.edges import out_edges +from discopop_explorer.functions.PEGraph.traversal.children import direct_children + + +def get_num_function_calls(pet: PEGraphX, node: Node, visited: List[Node]) -> int: + function_calls = 0 + visited.append(node) + + for child in direct_children(pet, node): + out_call_edges = out_edges(pet, child.id, EdgeType.CALLSNODE) + if len(out_call_edges) > 0: + for _, t, _ in out_call_edges: + function_calls += 1 + if t in visited: + continue + function_calls += get_num_function_calls(pet, pet.node_at(t), copy.deepcopy(visited)) + else: + function_calls += get_num_function_calls(pet, child, copy.deepcopy(visited)) + + return function_calls From d4c420e527dc9d16f3de909530b0e49f2d02d093 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 23 Oct 2024 10:13:46 +0200 Subject: [PATCH 097/105] fix: formatting --- .pre-commit-config.yaml | 2 +- .../utilities/statistics/output_statistics.py | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 65ad11f08..4002d6877 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -42,7 +42,7 @@ repos: # black -- more info: https://github.com/psf/black/blob/main/docs/integrations/source_version_control.md - repo: https://github.com/psf/black-pre-commit-mirror - rev: 23.9.1 + rev: 24.4.2 hooks: - id: black args: [--line-length=120] diff --git a/discopop_explorer/utilities/statistics/output_statistics.py b/discopop_explorer/utilities/statistics/output_statistics.py index a0e7c4f49..92053c556 100644 --- a/discopop_explorer/utilities/statistics/output_statistics.py +++ b/discopop_explorer/utilities/statistics/output_statistics.py @@ -85,23 +85,23 @@ def output_suggestion_statistics( for suggestion_id in suggestion_summed_cyclomatic_complexity_from_calls: if suggestion_id not in statistics_dict_by_suggestionID: statistics_dict_by_suggestionID[suggestion_id] = dict() - statistics_dict_by_suggestionID[suggestion_id][ - "suggestion_summed_cyclomatic_complexity_from_calls" - ] = suggestion_summed_cyclomatic_complexity_from_calls[suggestion_id] + statistics_dict_by_suggestionID[suggestion_id]["suggestion_summed_cyclomatic_complexity_from_calls"] = ( + suggestion_summed_cyclomatic_complexity_from_calls[suggestion_id] + ) for suggestion_id in suggestion_immediate_lines_of_code: if suggestion_id not in statistics_dict_by_suggestionID: statistics_dict_by_suggestionID[suggestion_id] = dict() - statistics_dict_by_suggestionID[suggestion_id][ - "suggestion_immediate_lines_of_code" - ] = suggestion_immediate_lines_of_code[suggestion_id] + statistics_dict_by_suggestionID[suggestion_id]["suggestion_immediate_lines_of_code"] = ( + suggestion_immediate_lines_of_code[suggestion_id] + ) for suggestion_id in suggestion_lines_of_code_including_calls: if suggestion_id not in statistics_dict_by_suggestionID: statistics_dict_by_suggestionID[suggestion_id] = dict() - statistics_dict_by_suggestionID[suggestion_id][ - "suggestion_lines_of_code_including_calls" - ] = suggestion_lines_of_code_including_calls[suggestion_id] + statistics_dict_by_suggestionID[suggestion_id]["suggestion_lines_of_code_including_calls"] = ( + suggestion_lines_of_code_including_calls[suggestion_id] + ) with open(statistics_file_by_suggestionID, "w+") as f: f.write(json.dumps(statistics_dict_by_suggestionID) + "\n") From c788aa8998497c0fac849801538ec6e283f5ff67 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 23 Oct 2024 11:36:14 +0200 Subject: [PATCH 098/105] fix: minor --- .../utilities/statistics/cyclomatic_complexity/boxplot.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/discopop_explorer/utilities/statistics/cyclomatic_complexity/boxplot.py b/discopop_explorer/utilities/statistics/cyclomatic_complexity/boxplot.py index 20e6b26e4..a55701cbb 100644 --- a/discopop_explorer/utilities/statistics/cyclomatic_complexity/boxplot.py +++ b/discopop_explorer/utilities/statistics/cyclomatic_complexity/boxplot.py @@ -58,6 +58,8 @@ def get_cyclomatic_complexities_for_boxplot( lower_quartile = sorted_cyclomatic_complexities[lower_quartile_idx] if len(sorted_cyclomatic_complexities) == 1: upper_quartile_idx = 0 + if len(sorted_cyclomatic_complexities) == upper_quartile_idx: + upper_quartile_idx -= 1 upper_quartile = sorted_cyclomatic_complexities[upper_quartile_idx] return cc_min, cc_max, cc_avg, lower_quartile, upper_quartile From 43868176a5923bc91fc954dee925c7443f9867a8 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 23 Oct 2024 12:48:07 +0200 Subject: [PATCH 099/105] fix: enable console output --- test/utils/subprocess_wrapper/command_execution_wrapper.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/utils/subprocess_wrapper/command_execution_wrapper.py b/test/utils/subprocess_wrapper/command_execution_wrapper.py index ec0a1b95d..6a4401055 100644 --- a/test/utils/subprocess_wrapper/command_execution_wrapper.py +++ b/test/utils/subprocess_wrapper/command_execution_wrapper.py @@ -9,6 +9,6 @@ def run_cmd(cmd: str, cwd: str, env: Dict[str, str]) -> None: executable="/bin/bash", shell=True, env=env, - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL, + # stdout=subprocess.DEVNULL, + # stderr=subprocess.DEVNULL, ) From d773f2964f0158b5d6d4712343bd92a083f04e3f Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 23 Oct 2024 13:00:04 +0200 Subject: [PATCH 100/105] fix: add missing __init__.py files --- discopop_explorer/utilities/statistics/__init__.py | 0 .../utilities/statistics/cyclomatic_complexity/__init__.py | 0 discopop_explorer/utilities/statistics/utilities/__init__.py | 0 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 discopop_explorer/utilities/statistics/__init__.py create mode 100644 discopop_explorer/utilities/statistics/cyclomatic_complexity/__init__.py create mode 100644 discopop_explorer/utilities/statistics/utilities/__init__.py diff --git a/discopop_explorer/utilities/statistics/__init__.py b/discopop_explorer/utilities/statistics/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/discopop_explorer/utilities/statistics/cyclomatic_complexity/__init__.py b/discopop_explorer/utilities/statistics/cyclomatic_complexity/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/discopop_explorer/utilities/statistics/utilities/__init__.py b/discopop_explorer/utilities/statistics/utilities/__init__.py new file mode 100644 index 000000000..e69de29bb From 0de72b350ba6e8a25ad6b3e525a997af7ae76596 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 23 Oct 2024 13:07:52 +0200 Subject: [PATCH 101/105] fix: disabled statistics collection by default --- discopop_explorer/__main__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/discopop_explorer/__main__.py b/discopop_explorer/__main__.py index b0dee494c..e21137359 100644 --- a/discopop_explorer/__main__.py +++ b/discopop_explorer/__main__.py @@ -105,7 +105,7 @@ def parse_args() -> ExplorerArguments: help="Path to llvm-cxxfilt executable. Required for task pattern detector if non-standard path should be used.", ) experimental_parser.add_argument( - "--disable-statistics", action="store_false", help="Disable the calculation and storing of statistics for code and generated suggestions." + "--enable-statistics", action="store_true", help="Disable the calculation and storing of statistics for code and generated suggestions." ) # fmt: on @@ -159,7 +159,7 @@ def parse_args() -> ExplorerArguments: log_level=arguments.log.upper(), write_log=arguments.write_log, load_existing_doall_and_reduction_patterns=arguments.load_existing_doall_and_reduction_patterns, - collect_statistics=arguments.disable_statistics, + collect_statistics=arguments.enable_statistics, ) From 3c28d73a38132ed6e3e64bd2f44d7e009231f759 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 23 Oct 2024 10:27:22 +0200 Subject: [PATCH 102/105] feat(explorer): cleanup old results before start --- discopop_explorer/discopop_explorer.py | 15 ++++++++++++--- discopop_library/LineMapping/delete.py | 16 ++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 discopop_library/LineMapping/delete.py diff --git a/discopop_explorer/discopop_explorer.py b/discopop_explorer/discopop_explorer.py index b5cb51895..e4481dce6 100644 --- a/discopop_explorer/discopop_explorer.py +++ b/discopop_explorer/discopop_explorer.py @@ -10,6 +10,7 @@ import json import logging import os +import shutil import sys import time from dataclasses import dataclass @@ -26,6 +27,7 @@ from discopop_library.HostpotLoader.HotspotType import HotspotType # type:ignore from discopop_library.LineMapping.initialize import initialize_line_mapping +from discopop_library.LineMapping.delete import delete_line_mapping from discopop_library.PathManagement.PathManagement import get_path, load_file_mapping from discopop_library.discopop_optimizer.Microbench.ExtrapInterpolatedMicrobench import ( ExtrapInterpolatedMicrobench, @@ -178,6 +180,16 @@ def run(arguments: ExplorerArguments) -> None: """Run the discopop_explorer with the given arguments""" logger = logging.getLogger("Explorer") + # reset environment, if previous results existed + if os.path.exists(os.path.join(arguments.project_path, "explorer")): + shutil.rmtree(os.path.join(arguments.project_path, "explorer")) + # reset file lock in case of prior crashes + if os.path.exists("next_free_pattern_id.txt.lock"): + os.remove("next_free_pattern_id.txt.lock") + if os.path.exists("next_free_pattern_id.txt"): + os.remove("next_free_pattern_id.txt") + delete_line_mapping(arguments.project_path) + # create explorer directory if not already present if not os.path.exists(os.path.join(arguments.project_path, "explorer")): os.mkdir(os.path.join(arguments.project_path, "explorer")) @@ -185,9 +197,6 @@ def run(arguments: ExplorerArguments) -> None: if not os.path.exists("next_free_pattern_id.txt"): with open("next_free_pattern_id.txt", "w") as f: f.write(str(0)) - # reset file lock in case of prior crashes - if os.path.exists("next_free_pattern_id.txt.lock"): - os.remove("next_free_pattern_id.txt.lock") if arguments.enable_profiling_dump_file is not None: profile = cProfile.Profile() diff --git a/discopop_library/LineMapping/delete.py b/discopop_library/LineMapping/delete.py new file mode 100644 index 000000000..da5e0958c --- /dev/null +++ b/discopop_library/LineMapping/delete.py @@ -0,0 +1,16 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. +import json +import os +from typing import Dict + + +def delete_line_mapping(discopop_path: str = "") -> None: + """deletes the saved line_mapping.json if it exists""" + if os.path.exists(os.path.join(discopop_path, "line_mapping.json")): + os.remove(os.path.join(discopop_path, "line_mapping.json")) From 95a4d1b7c5652e01f13cbc48e2aa3ac1107cd021 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 23 Oct 2024 11:16:15 +0200 Subject: [PATCH 103/105] feat(folder_structure): add proper utilities to setup and teardown --- discopop_explorer/discopop_explorer.py | 23 +----- discopop_library/FolderStructure/__init__.py | 0 discopop_library/FolderStructure/setup.py | 76 +++++++++++++++++++ discopop_library/FolderStructure/teardown.py | 64 ++++++++++++++++ .../PatchApplicator/patch_applicator.py | 14 +--- .../PatchGenerator/patch_generator.py | 22 +----- .../discopop_optimizer/optimizer.py | 7 +- 7 files changed, 152 insertions(+), 54 deletions(-) create mode 100644 discopop_library/FolderStructure/__init__.py create mode 100644 discopop_library/FolderStructure/setup.py create mode 100644 discopop_library/FolderStructure/teardown.py diff --git a/discopop_explorer/discopop_explorer.py b/discopop_explorer/discopop_explorer.py index e4481dce6..931e483a2 100644 --- a/discopop_explorer/discopop_explorer.py +++ b/discopop_explorer/discopop_explorer.py @@ -22,6 +22,8 @@ from discopop_explorer.functions.PEGraph.output.json import dump_to_pickled_json from discopop_explorer.utilities.statistics.collect_statistics import collect_statistics from discopop_library.ArgumentClasses.GeneralArguments import GeneralArguments # type: ignore +from discopop_library.FolderStructure.setup import setup_explorer +from discopop_library.FolderStructure.teardown import teardown_explorer from discopop_library.HostpotLoader.HotspotLoaderArguments import HotspotLoaderArguments from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType from discopop_library.HostpotLoader.HotspotType import HotspotType # type:ignore @@ -180,23 +182,7 @@ def run(arguments: ExplorerArguments) -> None: """Run the discopop_explorer with the given arguments""" logger = logging.getLogger("Explorer") - # reset environment, if previous results existed - if os.path.exists(os.path.join(arguments.project_path, "explorer")): - shutil.rmtree(os.path.join(arguments.project_path, "explorer")) - # reset file lock in case of prior crashes - if os.path.exists("next_free_pattern_id.txt.lock"): - os.remove("next_free_pattern_id.txt.lock") - if os.path.exists("next_free_pattern_id.txt"): - os.remove("next_free_pattern_id.txt") - delete_line_mapping(arguments.project_path) - - # create explorer directory if not already present - if not os.path.exists(os.path.join(arguments.project_path, "explorer")): - os.mkdir(os.path.join(arguments.project_path, "explorer")) - # create file to store next free pattern ids if not already present - if not os.path.exists("next_free_pattern_id.txt"): - with open("next_free_pattern_id.txt", "w") as f: - f.write(str(0)) + setup_explorer(arguments.project_path) if arguments.enable_profiling_dump_file is not None: profile = cProfile.Profile() @@ -282,9 +268,6 @@ def run(arguments: ExplorerArguments) -> None: with open(arguments.enable_json_file, "w+") as f: json.dump(res, f, indent=2, cls=PatternBaseSerializer) - # initialize the line_mapping.json - initialize_line_mapping(load_file_mapping(arguments.file_mapping_file), arguments.project_path) - print("Time taken for pattern detection: {0}".format(end - start)) # demonstration of Microbenchmark possibilities diff --git a/discopop_library/FolderStructure/__init__.py b/discopop_library/FolderStructure/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/discopop_library/FolderStructure/setup.py b/discopop_library/FolderStructure/setup.py new file mode 100644 index 000000000..23434d720 --- /dev/null +++ b/discopop_library/FolderStructure/setup.py @@ -0,0 +1,76 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +import json +import logging +import os + +from discopop_library.FolderStructure.teardown import teardown_explorer +from discopop_library.LineMapping.initialize import initialize_line_mapping +from discopop_library.PathManagement.PathManagement import load_file_mapping + +logger = logging.getLogger("FolderStructure").getChild("Setup") + + +def setup_explorer(path: str = "") -> None: + tmp_logger = logger.getChild("explorer") + tmp_logger.info("Start") + + teardown_explorer(path) + + # create explorer directory if not already present + if not os.path.exists(os.path.join(path, "explorer")): + os.mkdir(os.path.join(path, "explorer")) + # create file to store next free pattern ids if not already present + if not os.path.exists("next_free_pattern_id.txt"): + with open("next_free_pattern_id.txt", "w") as f: + f.write(str(0)) + + # initialize the line_mapping.json + initialize_line_mapping(load_file_mapping(os.path.join(path, "FileMapping.txt")), path) + + tmp_logger.info("Done") + + +def setup_patch_generator(path: str = "") -> None: + tmp_logger = logger.getChild("patch_generator") + tmp_logger.info("Start") + patch_generator_dir = os.path.join(path, "patch_generator") + if not os.path.exists(patch_generator_dir): + os.mkdir(patch_generator_dir) + + setup_patch_applicator() + + tmp_logger.info("Done") + + +def setup_patch_applicator(path: str = "") -> None: + tmp_logger = logger.getChild("patch_applicator") + tmp_logger.info("Start") + # create a directory for the patch applicator + patch_applicator_dir = os.path.join(path, "patch_applicator") + if not os.path.exists(patch_applicator_dir): + os.mkdir(patch_applicator_dir) + + # create a file to store applied suggestions + applied_suggestions_file = os.path.join(patch_applicator_dir, "applied_suggestions.json") + if not os.path.exists(applied_suggestions_file): + with open(applied_suggestions_file, "w+") as f: + f.write(json.dumps({"applied": []})) + + tmp_logger.info("Done") + + +def setup_optimizer(path: str = "") -> None: + tmp_logger = logger.getChild("optimizer") + tmp_logger.info("Start") + optimizer_dir = os.path.join(path, "optimizer") + if not os.path.exists(optimizer_dir): + os.mkdir(optimizer_dir) + + tmp_logger.info("Done") diff --git a/discopop_library/FolderStructure/teardown.py b/discopop_library/FolderStructure/teardown.py new file mode 100644 index 000000000..adbbc6d24 --- /dev/null +++ b/discopop_library/FolderStructure/teardown.py @@ -0,0 +1,64 @@ +# This file is part of the DiscoPoP software (http://www.discopop.tu-darmstadt.de) +# +# Copyright (c) 2020, Technische Universitaet Darmstadt, Germany +# +# This software may be modified and distributed under the terms of +# the 3-Clause BSD License. See the LICENSE file in the package base +# directory for details. + +import os +import shutil +from discopop_library.LineMapping.delete import delete_line_mapping + +import logging + +logger = logging.getLogger("FolderStructure").getChild("Teardown") + + +def teardown_explorer(path: str = "") -> None: + tmp_logger = logger.getChild("explorer") + tmp_logger.info("Start") + # reset environment, if previous results existed + if os.path.exists(os.path.join(path, "explorer")): + shutil.rmtree(os.path.join(path, "explorer")) + # reset file lock in case of prior crashes + if os.path.exists("next_free_pattern_id.txt.lock"): + os.remove("next_free_pattern_id.txt.lock") + if os.path.exists("next_free_pattern_id.txt"): + os.remove("next_free_pattern_id.txt") + delete_line_mapping(path) + + teardown_patch_generator(path) + teardown_patch_applicator(path) + teardown_optimizer(path) + + tmp_logger.info("Done") + + +def teardown_patch_generator(path: str = "") -> None: + tmp_logger = logger.getChild("patch_generator") + tmp_logger.info("Start") + patch_generator_dir = os.path.join(path, "patch_generator") + if os.path.exists(patch_generator_dir): + shutil.rmtree(patch_generator_dir) + teardown_patch_applicator(path) + tmp_logger.info("Done") + + +def teardown_patch_applicator(path: str = "") -> None: + tmp_logger = logger.getChild("patch_applicator") + tmp_logger.info("Start") + patch_applicator_dir = os.path.join(path, "patch_applicator") + if os.path.exists(patch_applicator_dir): + shutil.rmtree(patch_applicator_dir) + tmp_logger.info("Done") + + +def teardown_optimizer(path: str = "") -> None: + tmp_logger = logger.getChild("optimizer") + tmp_logger.info("Start") + optimizer_dir = os.path.join(path, "optimizer") + if os.path.exists(optimizer_dir): + shutil.rmtree(optimizer_dir) + + tmp_logger.info("Done") diff --git a/discopop_library/PatchApplicator/patch_applicator.py b/discopop_library/PatchApplicator/patch_applicator.py index 666ae8168..f10d83a00 100644 --- a/discopop_library/PatchApplicator/patch_applicator.py +++ b/discopop_library/PatchApplicator/patch_applicator.py @@ -8,6 +8,7 @@ import json import os +from discopop_library.FolderStructure.setup import setup_patch_applicator from discopop_library.PatchApplicator.PatchApplicatorArguments import PatchApplicatorArguments from discopop_library.PatchApplicator.apply import apply_patches from discopop_library.PatchApplicator.clear import clear_patches @@ -30,20 +31,9 @@ def run(arguments: PatchApplicatorArguments) -> int: print("Working directory: ", os.getcwd()) print(arguments) - # create a directory for the patch applicator + setup_patch_applicator(os.getcwd()) patch_applicator_dir = os.path.join(os.getcwd(), "patch_applicator") - if not os.path.exists(patch_applicator_dir): - if arguments.verbose: - print("Creating patch_applicator directory...") - os.mkdir(patch_applicator_dir) - - # create a file to store applied suggestions applied_suggestions_file = os.path.join(patch_applicator_dir, "applied_suggestions.json") - if not os.path.exists(applied_suggestions_file): - if arguments.verbose: - print("Creating applied_suggestions.json file...") - with open(applied_suggestions_file, "w+") as f: - f.write(json.dumps({"applied": []})) # load file mapping file_mapping_path = os.path.join(os.getcwd(), "FileMapping.txt") diff --git a/discopop_library/PatchGenerator/patch_generator.py b/discopop_library/PatchGenerator/patch_generator.py index fa3492eb2..147b32ccd 100644 --- a/discopop_library/PatchGenerator/patch_generator.py +++ b/discopop_library/PatchGenerator/patch_generator.py @@ -12,6 +12,7 @@ from typing import Dict from discopop_library.CodeGenerator.CodeGenerator import from_json_strings +from discopop_library.FolderStructure.setup import setup_patch_generator from discopop_library.JSONHandler.JSONHandler import read_patterns_from_json_to_json from discopop_library.PatchGenerator.PatchGeneratorArguments import PatchGeneratorArguments from discopop_library.PatchGenerator.from_optimizer_output import from_optimizer_output @@ -25,26 +26,9 @@ def run(arguments: PatchGeneratorArguments) -> None: if arguments.verbose: print("Started DiscoPoP Patch Generator...") - if arguments.verbose: - print("Creating patch_generator directory...") - patch_generator_dir = os.path.join(os.getcwd(), "patch_generator") - if not os.path.exists(patch_generator_dir): - os.mkdir(patch_generator_dir) - # for compatibility reasons, initialize the file to store applied patches if it doesn't exist already - # create a directory for the patch applicator - patch_applicator_dir = os.path.join(os.getcwd(), "patch_applicator") - if not os.path.exists(patch_applicator_dir): - if arguments.verbose: - print("Creating patch_applicator directory...") - os.mkdir(patch_applicator_dir) - # create a file to store applied suggestions - applied_suggestions_file = os.path.join(patch_applicator_dir, "applied_suggestions.json") - if not os.path.exists(applied_suggestions_file): - if arguments.verbose: - print("Creating applied_suggestions.json file...") - with open(applied_suggestions_file, "w+") as f: - f.write(json.dumps({"applied": []})) + setup_patch_generator(os.getcwd()) + patch_generator_dir = os.path.join(os.getcwd(), "patch_generator") # get pattern file to load if arguments.add_from_json != "None": diff --git a/discopop_library/discopop_optimizer/optimizer.py b/discopop_library/discopop_optimizer/optimizer.py index c9bc1a0b9..8e7d8f65a 100644 --- a/discopop_library/discopop_optimizer/optimizer.py +++ b/discopop_library/discopop_optimizer/optimizer.py @@ -18,6 +18,7 @@ from sympy import Float, Symbol # type: ignore from discopop_library.CodeGenerator.CodeGenerator import from_json_strings +from discopop_library.FolderStructure.setup import setup_optimizer from discopop_library.HostpotLoader.HotspotLoaderArguments import HotspotLoaderArguments from discopop_library.JSONHandler.JSONHandler import read_patterns_from_json_to_json from discopop_library.PatchGenerator.PatchGeneratorArguments import PatchGeneratorArguments @@ -90,10 +91,10 @@ def run_passive_optimizer(arguments: OptimizerArguments) -> None: if arguments.verbose: print("Started DiscoPoP Optimizer...") print("Creating optimizer directory...") - optimizer_dir = os.path.join(os.getcwd(), "optimizer") - if not os.path.exists(optimizer_dir): - os.mkdir(optimizer_dir) + setup_optimizer(os.getcwd()) + + optimizer_dir = os.path.join(os.getcwd(), "optimizer") explorer_dir = os.path.join(os.getcwd(), "explorer") profiler_dir = os.path.join(os.getcwd(), "profiler") pattern_file_path = os.path.join(explorer_dir, "patterns.json") From c9909d4b885fe29f1164faab2a5480109e0928c9 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 23 Oct 2024 14:19:31 +0200 Subject: [PATCH 104/105] feat(explorer): automatically create patch files --- discopop_explorer/discopop_explorer.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/discopop_explorer/discopop_explorer.py b/discopop_explorer/discopop_explorer.py index 931e483a2..1f354570e 100644 --- a/discopop_explorer/discopop_explorer.py +++ b/discopop_explorer/discopop_explorer.py @@ -11,6 +11,7 @@ import logging import os import shutil +import subprocess import sys import time from dataclasses import dataclass @@ -30,6 +31,7 @@ from discopop_library.LineMapping.initialize import initialize_line_mapping from discopop_library.LineMapping.delete import delete_line_mapping +from discopop_library.PatchGenerator.PatchGeneratorArguments import PatchGeneratorArguments from discopop_library.PathManagement.PathManagement import get_path, load_file_mapping from discopop_library.discopop_optimizer.Microbench.ExtrapInterpolatedMicrobench import ( ExtrapInterpolatedMicrobench, @@ -270,6 +272,12 @@ def run(arguments: ExplorerArguments) -> None: print("Time taken for pattern detection: {0}".format(end - start)) + # create applicable patch files from the found suggestions + logger.info("executing discopop_patch_generator") + out = subprocess.check_output(["discopop_patch_generator"], cwd=arguments.project_path).decode("utf-8") + logger.debug("\t Out:\n" + out) + logger.info("\tDone.") + # demonstration of Microbenchmark possibilities if arguments.microbench_file is not None: microbench_file = get_path( From 8d7b7d0945e75a8a5ab46b6378ce14f18784f487 Mon Sep 17 00:00:00 2001 From: Lukas Rothenberger Date: Wed, 23 Oct 2024 14:34:19 +0200 Subject: [PATCH 105/105] doc: updated version file --- discopop_library/global_data/version/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/discopop_library/global_data/version/VERSION b/discopop_library/global_data/version/VERSION index e4604e3af..fcdb2e109 100644 --- a/discopop_library/global_data/version/VERSION +++ b/discopop_library/global_data/version/VERSION @@ -1 +1 @@ -3.2.1 +4.0.0