From 9fa45eab44238904dc6ea7a273594378df651d46 Mon Sep 17 00:00:00 2001 From: John McCall Date: Fri, 10 Apr 2020 00:13:49 -0400 Subject: [PATCH] Rename OptimalLayout to OptimizedStructLayout at Chris's request. --- ...ptimalLayout.h => OptimizedStructLayout.h} | 42 ++++++++++++------- lib/Support/CMakeLists.txt | 2 +- ...alLayout.cpp => OptimizedStructLayout.cpp} | 37 ++++++++-------- lib/Transforms/Coroutines/CoroFrame.cpp | 10 ++--- unittests/Support/CMakeLists.txt | 2 +- ...Test.cpp => OptimizedStructLayoutTest.cpp} | 22 +++++----- utils/gn/secondary/llvm/lib/Support/BUILD.gn | 2 +- .../secondary/llvm/unittests/Support/BUILD.gn | 2 +- 8 files changed, 64 insertions(+), 55 deletions(-) rename include/llvm/Support/{OptimalLayout.h => OptimizedStructLayout.h} (74%) rename lib/Support/{OptimalLayout.cpp => OptimizedStructLayout.cpp} (93%) rename unittests/Support/{OptimalLayoutTest.cpp => OptimizedStructLayoutTest.cpp} (82%) diff --git a/include/llvm/Support/OptimalLayout.h b/include/llvm/Support/OptimizedStructLayout.h similarity index 74% rename from include/llvm/Support/OptimalLayout.h rename to include/llvm/Support/OptimizedStructLayout.h index 870dc78791b..773ddfeaf13 100644 --- a/include/llvm/Support/OptimalLayout.h +++ b/include/llvm/Support/OptimizedStructLayout.h @@ -1,4 +1,4 @@ -//===-- OptimalLayout.h - Optimal data layout algorithm -----------*- C++ -*-=// +//===-- OptimizedStructLayout.h - Struct layout algorithm ---------*- C++ -*-=// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -8,19 +8,31 @@ /// /// This file provides an interface for laying out a sequence of fields /// as a struct in a way that attempts to minimizes the total space -/// requirements of the struct. +/// requirements of the struct while still satisfying the layout +/// requirements of the individual fields. The resulting layout may be +/// substantially more compact than simply laying out the fields in their +/// original order. /// -/// The word "optimal" is a misnomer in several ways. First, minimizing -/// space usage doesn't necessarily yield optimal performance because it -/// may decrease locality. Second, there is no known efficient algorithm -/// that guarantees a minimal layout for arbitrary inputs. Nonetheless, -/// this algorithm is likely to produce much more compact layouts than -/// would be produced by just allocating space in a buffer. +/// Fields may be pre-assigned fixed offsets. They may also be given sizes +/// that are not multiples of their alignments. There is no currently no +/// way to describe that a field has interior padding that other fields may +/// be allocated into. +/// +/// This algorithm does not claim to be "optimal" for several reasons: +/// +/// - First, it does not guarantee that the result is minimal in size. +/// There is no known efficient algoorithm to achieve minimality for +/// unrestricted inputs. Nonetheless, this algorithm +/// +/// - Second, there are other ways that a struct layout could be optimized +/// besides space usage, such as locality. This layout may have a mixed +/// impact on locality: less overall memory may be used, but adjacent +/// fields in the original array may be moved further from one another. /// //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_OPTIMALLAYOUT_H -#define LLVM_SUPPORT_OPTIMALLAYOUT_H +#ifndef LLVM_SUPPORT_OPTIMIZEDSTRUCTLAYOUT_H +#define LLVM_SUPPORT_OPTIMIZEDSTRUCTLAYOUT_H #include "llvm/Support/Alignment.h" #include "llvm/ADT/ArrayRef.h" @@ -29,13 +41,13 @@ namespace llvm { /// A field in a structure. -struct OptimalLayoutField { +struct OptimizedStructLayoutField { /// A special value for Offset indicating that the field can be moved /// anywhere. static constexpr uint64_t FlexibleOffset = ~(uint64_t)0; - OptimalLayoutField(const void *Id, uint64_t Size, Align Alignment, - uint64_t FixedOffset = FlexibleOffset) + OptimizedStructLayoutField(const void *Id, uint64_t Size, Align Alignment, + uint64_t FixedOffset = FlexibleOffset) : Offset(FixedOffset), Size(Size), Id(Id), Alignment(Alignment) { assert(Size > 0 && "adding an empty field to the layout"); } @@ -122,8 +134,8 @@ struct OptimalLayoutField { /// The return value is the total size of the struct and its required /// alignment. Note that the total size is not rounded up to a multiple /// of the required alignment; clients which require this can do so easily. -std::pair -performOptimalLayout(MutableArrayRef Fields); +std::pair performOptimizedStructLayout( + MutableArrayRef Fields); } // namespace llvm diff --git a/lib/Support/CMakeLists.txt b/lib/Support/CMakeLists.txt index 25e1be67330..897f183b660 100644 --- a/lib/Support/CMakeLists.txt +++ b/lib/Support/CMakeLists.txt @@ -117,7 +117,7 @@ add_llvm_component_library(LLVMSupport MemoryBuffer.cpp MD5.cpp NativeFormatting.cpp - OptimalLayout.cpp + OptimizedStructLayout.cpp Optional.cpp Parallel.cpp PluginLoader.cpp diff --git a/lib/Support/OptimalLayout.cpp b/lib/Support/OptimizedStructLayout.cpp similarity index 93% rename from lib/Support/OptimalLayout.cpp rename to lib/Support/OptimizedStructLayout.cpp index 93f912bf73a..9bbd767c5ce 100644 --- a/lib/Support/OptimalLayout.cpp +++ b/lib/Support/OptimizedStructLayout.cpp @@ -1,4 +1,4 @@ -//===--- OptimalLayout.cpp - Optimal data layout algorithm ----------------===// +//===--- OptimizedStructLayout.cpp - Optimal data layout algorithm ----------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,16 +6,18 @@ // //===----------------------------------------------------------------------===// // -// This file implements the performOptimalLayout interface. +// This file implements the performOptimizedStructLayout interface. // //===----------------------------------------------------------------------===// -#include "llvm/Support/OptimalLayout.h" +#include "llvm/Support/OptimizedStructLayout.h" using namespace llvm; +using Field = OptimizedStructLayoutField; + #ifndef NDEBUG -static void checkValidLayout(ArrayRef Fields, uint64_t Size, +static void checkValidLayout(ArrayRef Fields, uint64_t Size, Align MaxAlign) { uint64_t LastEnd = 0; Align ComputedMaxAlign; @@ -37,7 +39,7 @@ static void checkValidLayout(ArrayRef Fields, uint64_t Size, #endif std::pair -llvm::performOptimalLayout(MutableArrayRef Fields) { +llvm::performOptimizedStructLayout(MutableArrayRef Fields) { #ifndef NDEBUG // Do some simple precondition checks. { @@ -101,8 +103,7 @@ llvm::performOptimalLayout(MutableArrayRef Fields) { // important if we get into the gap-filling stage below, but it // doesn't hurt here. array_pod_sort(FirstFlexible, E, - [](const OptimalLayoutField *lhs, - const OptimalLayoutField *rhs) -> int { + [](const Field *lhs, const Field *rhs) -> int { // Decreasing alignment. if (lhs->Alignment != rhs->Alignment) return (lhs->Alignment < rhs->Alignment ? 1 : -1); @@ -240,13 +241,13 @@ llvm::performOptimalLayout(MutableArrayRef Fields) { /// monotonically descending in size and otherwise in the original order. /// /// We remove the queue from the array as soon as this is empty. - OptimalLayoutField *Head; + OptimizedStructLayoutField *Head; /// The alignment requirement of the queue. Align Alignment; - static OptimalLayoutField *getNext(OptimalLayoutField *Cur) { - return static_cast(Cur->Scratch); + static Field *getNext(Field *Cur) { + return static_cast(Cur->Scratch); } }; SmallVector FlexibleFieldsByAlignment; @@ -290,9 +291,7 @@ llvm::performOptimalLayout(MutableArrayRef Fields) { #endif /// Helper function to remove a field from a queue. - auto spliceFromQueue = [&](AlignmentQueue *Queue, - OptimalLayoutField *Last, - OptimalLayoutField *Cur) { + auto spliceFromQueue = [&](AlignmentQueue *Queue, Field *Last, Field *Cur) { assert(Last ? Queue->getNext(Last) == Cur : Queue->Head == Cur); // If we're removing Cur from a non-initial position, splice it out @@ -319,7 +318,7 @@ llvm::performOptimalLayout(MutableArrayRef Fields) { // Do layout into a local array. Doing this in-place on Fields is // not really feasible. - SmallVector Layout; + SmallVector Layout; Layout.reserve(Fields.size()); // The offset that we're currently looking to insert at (or after). @@ -327,9 +326,7 @@ llvm::performOptimalLayout(MutableArrayRef Fields) { // Helper function to splice Cur out of the given queue and add it // to the layout at the given offset. - auto addToLayout = [&](AlignmentQueue *Queue, - OptimalLayoutField *Last, - OptimalLayoutField *Cur, + auto addToLayout = [&](AlignmentQueue *Queue, Field *Last, Field *Cur, uint64_t Offset) -> bool { assert(Offset == alignTo(LastEnd, Cur->Alignment)); @@ -362,8 +359,8 @@ llvm::performOptimalLayout(MutableArrayRef Fields) { // Find the matching field. Note that this should always find // something because of the MinSize check above. - for (OptimalLayoutField *Cur = Queue->Head, *Last = nullptr; - true; Last = Cur, Cur = Queue->getNext(Cur)) { + for (Field *Cur = Queue->Head, *Last = nullptr; true; + Last = Cur, Cur = Queue->getNext(Cur)) { assert(Cur && "didn't find a match in queue despite its MinSize"); if (Cur->Size <= MaxViableSize) return addToLayout(Queue, Last, Cur, StartOffset); @@ -441,7 +438,7 @@ llvm::performOptimalLayout(MutableArrayRef Fields) { // Copy the layout back into place. assert(Layout.size() == Fields.size()); memcpy(Fields.data(), Layout.data(), - Fields.size() * sizeof(OptimalLayoutField)); + Fields.size() * sizeof(OptimizedStructLayoutField)); #ifndef NDEBUG // Make a final check that the layout is valid. diff --git a/lib/Transforms/Coroutines/CoroFrame.cpp b/lib/Transforms/Coroutines/CoroFrame.cpp index e166e28cbcd..204a4697b70 100644 --- a/lib/Transforms/Coroutines/CoroFrame.cpp +++ b/lib/Transforms/Coroutines/CoroFrame.cpp @@ -29,7 +29,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/circular_raw_ostream.h" -#include "llvm/Support/OptimalLayout.h" +#include "llvm/Support/OptimizedStructLayout.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/PromoteMemToReg.h" @@ -412,7 +412,7 @@ public: // Everything else has a flexible offset. } else { - Offset = OptimalLayoutField::FlexibleOffset; + Offset = OptimizedStructLayoutField::FlexibleOffset; } Fields.push_back({FieldSize, Offset, ForSpill, Ty, 0, @@ -445,7 +445,7 @@ void FrameTypeBuilder::finish(StructType *Ty) { // Prepare the optimal-layout field array. // The Id in the layout field is a pointer to our Field for it. - SmallVector LayoutFields; + SmallVector LayoutFields; LayoutFields.reserve(Fields.size()); for (auto &Field : Fields) { LayoutFields.emplace_back(&Field, Field.Size, Field.Alignment, @@ -453,11 +453,11 @@ void FrameTypeBuilder::finish(StructType *Ty) { } // Perform layout. - auto SizeAndAlign = performOptimalLayout(LayoutFields); + auto SizeAndAlign = performOptimizedStructLayout(LayoutFields); StructSize = SizeAndAlign.first; StructAlign = SizeAndAlign.second; - auto getField = [](const OptimalLayoutField &LayoutField) -> Field & { + auto getField = [](const OptimizedStructLayoutField &LayoutField) -> Field & { return *static_cast(const_cast(LayoutField.Id)); }; diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt index a570a0406d7..b6ed410c0f7 100644 --- a/unittests/Support/CMakeLists.txt +++ b/unittests/Support/CMakeLists.txt @@ -52,7 +52,7 @@ add_llvm_unittest(SupportTests MemoryBufferTest.cpp MemoryTest.cpp NativeFormatTests.cpp - OptimalLayoutTest.cpp + OptimizedStructLayoutTest.cpp ParallelTest.cpp Path.cpp ProcessTest.cpp diff --git a/unittests/Support/OptimalLayoutTest.cpp b/unittests/Support/OptimizedStructLayoutTest.cpp similarity index 82% rename from unittests/Support/OptimalLayoutTest.cpp rename to unittests/Support/OptimizedStructLayoutTest.cpp index a31fbaf3f2e..26d5e27b14b 100644 --- a/unittests/Support/OptimalLayoutTest.cpp +++ b/unittests/Support/OptimizedStructLayoutTest.cpp @@ -1,4 +1,4 @@ -//=== - llvm/unittest/Support/OptimalLayoutTest.cpp - Layout tests --------===// +//=== - unittest/Support/OptimizedStructLayoutTest.cpp - Layout tests -----===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/OptimalLayout.h" +#include "llvm/Support/OptimizedStructLayout.h" #include "gtest/gtest.h" using namespace llvm; @@ -33,7 +33,7 @@ public: LayoutTest &flexible(uint64_t Size, uint64_t Alignment, uint64_t ExpectedOffset) { Fields.push_back({Size, Align(Alignment), - OptimalLayoutField::FlexibleOffset, ExpectedOffset}); + OptimizedStructLayoutField::FlexibleOffset, ExpectedOffset}); return *this; } @@ -43,12 +43,12 @@ public: } void verify(uint64_t ExpectedSize, uint64_t ExpectedAlignment) { - SmallVector LayoutFields; + SmallVector LayoutFields; LayoutFields.reserve(Fields.size()); for (auto &F : Fields) LayoutFields.emplace_back(&F, F.Size, F.Alignment, F.ForcedOffset); - auto SizeAndAlign = performOptimalLayout(LayoutFields); + auto SizeAndAlign = performOptimizedStructLayout(LayoutFields); EXPECT_EQ(SizeAndAlign.first, ExpectedSize); EXPECT_EQ(SizeAndAlign.second, Align(ExpectedAlignment)); @@ -64,7 +64,7 @@ public: } -TEST(OptimalLayoutTest, Basic) { +TEST(OptimizedStructLayoutTest, Basic) { LayoutTest() .flexible(12, 4, 8) .flexible(8, 8, 0) @@ -72,7 +72,7 @@ TEST(OptimalLayoutTest, Basic) { .verify(24, 8); } -TEST(OptimalLayoutTest, OddSize) { +TEST(OptimizedStructLayoutTest, OddSize) { LayoutTest() .flexible(8, 8, 16) .flexible(4, 4, 12) @@ -81,7 +81,7 @@ TEST(OptimalLayoutTest, OddSize) { .verify(24, 8); } -TEST(OptimalLayoutTest, Gaps) { +TEST(OptimizedStructLayoutTest, Gaps) { LayoutTest() .fixed(4, 4, 8) .fixed(4, 4, 16) @@ -92,7 +92,7 @@ TEST(OptimalLayoutTest, Gaps) { .verify(24, 4); } -TEST(OptimalLayoutTest, Greed) { +TEST(OptimizedStructLayoutTest, Greed) { // The greedy algorithm doesn't find the optimal layout here, which // would be to put the 5-byte field at the end. LayoutTest() @@ -104,7 +104,7 @@ TEST(OptimalLayoutTest, Greed) { .verify(24, 4); } -TEST(OptimalLayoutTest, Jagged) { +TEST(OptimizedStructLayoutTest, Jagged) { LayoutTest() .flexible(1, 2, 18) .flexible(13, 8, 0) @@ -112,7 +112,7 @@ TEST(OptimalLayoutTest, Jagged) { .verify(19, 8); } -TEST(OptimalLayoutTest, GardenPath) { +TEST(OptimizedStructLayoutTest, GardenPath) { // The 4-byte-aligned field is our highest priority, but the less-aligned // fields keep leaving the end offset mis-aligned. LayoutTest() diff --git a/utils/gn/secondary/llvm/lib/Support/BUILD.gn b/utils/gn/secondary/llvm/lib/Support/BUILD.gn index 13ffdaedfb6..33fac467a5c 100644 --- a/utils/gn/secondary/llvm/lib/Support/BUILD.gn +++ b/utils/gn/secondary/llvm/lib/Support/BUILD.gn @@ -95,7 +95,7 @@ static_library("Support") { "MathExtras.cpp", "MemoryBuffer.cpp", "NativeFormatting.cpp", - "OptimalLayout.cpp", + "OptimizedStructLayout.cpp", "Optional.cpp", "Parallel.cpp", "PluginLoader.cpp", diff --git a/utils/gn/secondary/llvm/unittests/Support/BUILD.gn b/utils/gn/secondary/llvm/unittests/Support/BUILD.gn index c25323955b9..b58a6aba73d 100644 --- a/utils/gn/secondary/llvm/unittests/Support/BUILD.gn +++ b/utils/gn/secondary/llvm/unittests/Support/BUILD.gn @@ -55,7 +55,7 @@ unittest("SupportTests") { "MemoryBufferTest.cpp", "MemoryTest.cpp", "NativeFormatTests.cpp", - "OptimalLayoutTest.cpp", + "OptimizedStructLayoutTest.cpp", "ParallelTest.cpp", "Path.cpp", "ProcessTest.cpp",