diff --git a/llvm/test/CodeGen/X86/code_placement_ext_tsp.ll b/llvm/test/CodeGen/X86/code_placement_ext_tsp.ll --- a/llvm/test/CodeGen/X86/code_placement_ext_tsp.ll +++ b/llvm/test/CodeGen/X86/code_placement_ext_tsp.ll @@ -1,3 +1,4 @@ +;; See also llvm/unittests/Transforms/Utils/CodeLayoutTest.cpp ; RUN: llc -mcpu=corei7 -mtriple=x86_64-linux -enable-ext-tsp-block-placement=1 < %s | FileCheck %s ; RUN: llc -mcpu=corei7 -mtriple=x86_64-linux -enable-ext-tsp-block-placement=1 -ext-tsp-chain-split-threshold=0 -ext-tsp-enable-chain-split-along-jumps=0 < %s | FileCheck %s -check-prefix=CHECK2 diff --git a/llvm/unittests/Transforms/Utils/CMakeLists.txt b/llvm/unittests/Transforms/Utils/CMakeLists.txt --- a/llvm/unittests/Transforms/Utils/CMakeLists.txt +++ b/llvm/unittests/Transforms/Utils/CMakeLists.txt @@ -15,6 +15,7 @@ CallPromotionUtilsTest.cpp CloningTest.cpp CodeExtractorTest.cpp + CodeLayoutTest.cpp CodeMoverUtilsTest.cpp DebugifyTest.cpp FunctionComparatorTest.cpp diff --git a/llvm/unittests/Transforms/Utils/CodeLayoutTest.cpp b/llvm/unittests/Transforms/Utils/CodeLayoutTest.cpp new file mode 100644 --- /dev/null +++ b/llvm/unittests/Transforms/Utils/CodeLayoutTest.cpp @@ -0,0 +1,63 @@ +#include "llvm/Transforms/Utils/CodeLayout.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include + +using namespace llvm; +using namespace llvm::codelayout; +using testing::ElementsAreArray; + +namespace { +TEST(CodeLayout, ThreeFunctions) { + // Place the most likely successor (2) first. + { + const uint64_t Counts[3] = {140, 40, 140}; + const std::vector Sizes(std::size(Counts), 9); + const EdgeCount Edges[] = {{0, 1, 40}, {0, 2, 100}, {1, 2, 40}}; + const std::vector CallOffsets(std::size(Edges), 5); + auto Order = computeCacheDirectedLayout(Sizes, Counts, Edges, CallOffsets); + EXPECT_THAT(Order, ElementsAreArray({0, 2, 1})); + } + + // Prefer fallthroughs even in the presence of a heavy successor. + { + const uint64_t Counts[3] = {180, 80, 180}; + const std::vector Sizes(std::size(Counts), 9); + const EdgeCount Edges[] = {{0, 1, 80}, {0, 2, 100}, {1, 2, 80}}; + const uint64_t CallOffsets[] = {9, 5, 9}; + auto Order = computeCacheDirectedLayout(Sizes, Counts, Edges, CallOffsets); + EXPECT_THAT(Order, ElementsAreArray({0, 1, 2})); + } +} + +TEST(CodeLayout, HotChain) { + // Place the hot chain (0,3,4,2) continuously. + { + const uint64_t Counts[5] = {22, 7, 22, 15, 46}; + const std::vector Sizes(std::size(Counts), 9); + const EdgeCount Edges[] = {{0, 1, 7}, {1, 2, 7}, {0, 3, 15}, + {3, 4, 15}, {4, 4, 31}, {4, 2, 15}}; + const std::vector CallOffsets(std::size(Edges), 5); + auto Order = computeCacheDirectedLayout(Sizes, Counts, Edges, CallOffsets); + EXPECT_THAT(Order, ElementsAreArray({0, 3, 4, 2, 1})); + } +} + +TEST(CodeLayout, BreakLoop) { + // There are two loops (1,2,3) and (1,2,4). It is beneficial to place 4 + // elsewhere. + const uint64_t Counts[6] = {177, 371, 196, 124, 70, 177}; + std::vector Sizes(std::size(Counts), 9); + const EdgeCount Edges[] = {{0, 1, 177}, {1, 2, 196}, {2, 3, 124}, {3, 1, 124}, + {1, 5, 177}, {2, 4, 79}, {4, 1, 70}}; + const std::vector CallOffsets(std::size(Edges), 5); + auto Order = computeCacheDirectedLayout(Sizes, Counts, Edges, CallOffsets); + EXPECT_THAT(Order, ElementsAreArray({4, 0, 1, 2, 3, 5})); + + // When node 0 is larger, it is beneficial to move node 4 closer to the + // (1,2,3) loop. + Sizes[0] = 18; + Order = computeCacheDirectedLayout(Sizes, Counts, Edges, CallOffsets); + EXPECT_THAT(Order, ElementsAreArray({0, 4, 1, 2, 3, 5})); +} +} // namespace