diff options
-rw-r--r-- | llvm/include/llvm/ProfileData/InstrProfWriter.h | 2 | ||||
-rw-r--r-- | llvm/lib/ProfileData/InstrProfWriter.cpp | 17 | ||||
-rw-r--r-- | llvm/unittests/ProfileData/InstrProfTest.cpp | 115 |
3 files changed, 71 insertions, 63 deletions
diff --git a/llvm/include/llvm/ProfileData/InstrProfWriter.h b/llvm/include/llvm/ProfileData/InstrProfWriter.h index 7e4f6011a39..ca2f71b6d90 100644 --- a/llvm/include/llvm/ProfileData/InstrProfWriter.h +++ b/llvm/include/llvm/ProfileData/InstrProfWriter.h @@ -51,7 +51,7 @@ public: std::unique_ptr<MemoryBuffer> writeBuffer(); // Internal interface for testing purpose only. - void setValueProfDataEndianness(support::endianness Endianness); + static support::endianness getValueProfDataEndianness(); private: void writeImpl(ProfOStream &OS); diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp index 4c7f5de26aa..7945469268c 100644 --- a/llvm/lib/ProfileData/InstrProfWriter.cpp +++ b/llvm/lib/ProfileData/InstrProfWriter.cpp @@ -14,12 +14,16 @@ #include "llvm/ProfileData/InstrProfWriter.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/EndianStream.h" #include "llvm/Support/OnDiskHashTable.h" #include <tuple> using namespace llvm; +static cl::opt<bool> WriteVPInBE("write-vp-data-in-big", cl::ReallyHidden, + cl::init(false)); + // A struct to define how the data stream should be patched. For Indexed // profiling, only uint64_t data type is needed. struct PatchItem { @@ -74,8 +78,6 @@ public: } namespace { -static support::endianness ValueProfDataEndianness = support::little; - class InstrProfRecordTrait { public: typedef StringRef key_type; @@ -134,17 +136,18 @@ public: std::unique_ptr<ValueProfData> VDataPtr = ValueProfData::serializeFrom(ProfileData.second); uint32_t S = VDataPtr->getSize(); - VDataPtr->swapBytesFromHost(ValueProfDataEndianness); + VDataPtr->swapBytesFromHost( + InstrProfWriter::getValueProfDataEndianness()); Out.write((const char *)VDataPtr.get(), S); } } }; } -// Internal interface for testing purpose only. -void InstrProfWriter::setValueProfDataEndianness( - support::endianness Endianness) { - ValueProfDataEndianness = Endianness; +support::endianness InstrProfWriter::getValueProfDataEndianness() { + if (WriteVPInBE) + return support::big; + return support::little; } std::error_code InstrProfWriter::addRecord(InstrProfRecord &&I, diff --git a/llvm/unittests/ProfileData/InstrProfTest.cpp b/llvm/unittests/ProfileData/InstrProfTest.cpp index ef79d51ede5..bb9f1c7a2f7 100644 --- a/llvm/unittests/ProfileData/InstrProfTest.cpp +++ b/llvm/unittests/ProfileData/InstrProfTest.cpp @@ -12,6 +12,7 @@ #include "llvm/IR/Module.h" #include "llvm/ProfileData/InstrProfReader.h" #include "llvm/ProfileData/InstrProfWriter.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Compression.h" #include "gtest/gtest.h" @@ -145,6 +146,7 @@ TEST_F(InstrProfTest, get_icall_data_read_write) { InstrProfValueData VD3[] = {{(uint64_t) "callee1", 1}}; Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr); + ASSERT_EQ(support::little, InstrProfWriter::getValueProfDataEndianness()); Writer.addRecord(std::move(Record1)); Writer.addRecord(std::move(Record2)); Writer.addRecord(std::move(Record3)); @@ -192,6 +194,7 @@ TEST_F(InstrProfTest, get_icall_data_read_write_with_weight) { InstrProfValueData VD3[] = {{(uint64_t) "callee1", 1}}; Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr); + ASSERT_EQ(support::little, InstrProfWriter::getValueProfDataEndianness()); Writer.addRecord(std::move(Record1), 10); Writer.addRecord(std::move(Record2)); Writer.addRecord(std::move(Record3)); @@ -218,58 +221,6 @@ TEST_F(InstrProfTest, get_icall_data_read_write_with_weight) { ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1")); } -TEST_F(InstrProfTest, get_icall_data_read_write_big_endian) { - InstrProfRecord Record1("caller", 0x1234, {1, 2}); - InstrProfRecord Record2("callee1", 0x1235, {3, 4}); - InstrProfRecord Record3("callee2", 0x1235, {3, 4}); - InstrProfRecord Record4("callee3", 0x1235, {3, 4}); - - // 4 value sites. - Record1.reserveSites(IPVK_IndirectCallTarget, 4); - InstrProfValueData VD0[] = {{(uint64_t) "callee1", 1}, - {(uint64_t) "callee2", 2}, - {(uint64_t) "callee3", 3}}; - Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr); - // No value profile data at the second site. - Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); - InstrProfValueData VD2[] = {{(uint64_t) "callee1", 1}, - {(uint64_t) "callee2", 2}}; - Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr); - InstrProfValueData VD3[] = {{(uint64_t) "callee1", 1}}; - Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr); - - Writer.addRecord(std::move(Record1)); - Writer.addRecord(std::move(Record2)); - Writer.addRecord(std::move(Record3)); - Writer.addRecord(std::move(Record4)); - - // Set big endian output. - Writer.setValueProfDataEndianness(support::big); - - auto Profile = Writer.writeBuffer(); - readProfile(std::move(Profile)); - - // Set big endian input. - Reader->setValueProfDataEndianness(support::big); - - ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234); - ASSERT_TRUE(NoError(R.getError())); - ASSERT_EQ(4U, R.get().getNumValueSites(IPVK_IndirectCallTarget)); - ASSERT_EQ(3U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); - ASSERT_EQ(0U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 1)); - ASSERT_EQ(2U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 2)); - ASSERT_EQ(1U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); - - std::unique_ptr<InstrProfValueData[]> VD = - R.get().getValueForSite(IPVK_IndirectCallTarget, 0); - ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3")); - ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2")); - ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1")); - - // Restore little endian default: - Writer.setValueProfDataEndianness(support::little); -} - TEST_F(InstrProfTest, get_icall_data_merge1) { static const char caller[] = "caller"; static const char callee1[] = "callee1"; @@ -322,11 +273,11 @@ TEST_F(InstrProfTest, get_icall_data_merge1) { Record12.addValueData(IPVK_IndirectCallTarget, 3, nullptr, 0, nullptr); - InstrProfValueData VD42[] = {{uint64_t(callee1), 1}, - {uint64_t(callee2), 2}, - {uint64_t(callee3), 3}}; + InstrProfValueData VD42[] = { + {uint64_t(callee1), 1}, {uint64_t(callee2), 2}, {uint64_t(callee3), 3}}; Record12.addValueData(IPVK_IndirectCallTarget, 4, VD42, 3, nullptr); + ASSERT_EQ(support::little, InstrProfWriter::getValueProfDataEndianness()); Writer.addRecord(std::move(Record11)); // Merge profile data. Writer.addRecord(std::move(Record12)); @@ -418,6 +369,7 @@ TEST_F(InstrProfTest, get_icall_data_merge1_saturation) { auto Result5 = Writer.addRecord(std::move(Record5)); ASSERT_EQ(Result5, instrprof_error::counter_overflow); + ASSERT_EQ(support::little, InstrProfWriter::getValueProfDataEndianness()); auto Profile = Writer.writeBuffer(); readProfile(std::move(Profile)); @@ -466,6 +418,7 @@ TEST_F(InstrProfTest, get_icall_data_merge_site_trunc) { Record12.addValueData(IPVK_IndirectCallTarget, 0, VD1, 255, nullptr); Record12.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); + ASSERT_EQ(support::little, InstrProfWriter::getValueProfDataEndianness()); Writer.addRecord(std::move(Record11)); // Merge profile data. Writer.addRecord(std::move(Record12)); @@ -767,4 +720,56 @@ TEST_F(InstrProfTest, instr_prof_symtab_compression_test) { } } +// Keep this the last test case as it sets the VP data endianness +TEST_F(InstrProfTest, get_icall_data_read_write_big_endian) { + InstrProfRecord Record1("caller", 0x1234, {1, 2}); + InstrProfRecord Record2("callee1", 0x1235, {3, 4}); + InstrProfRecord Record3("callee2", 0x1235, {3, 4}); + InstrProfRecord Record4("callee3", 0x1235, {3, 4}); + + // 4 value sites. + Record1.reserveSites(IPVK_IndirectCallTarget, 4); + InstrProfValueData VD0[] = {{(uint64_t) "callee1", 1}, + {(uint64_t) "callee2", 2}, + {(uint64_t) "callee3", 3}}; + Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr); + // No value profile data at the second site. + Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); + InstrProfValueData VD2[] = {{(uint64_t) "callee1", 1}, + {(uint64_t) "callee2", 2}}; + Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr); + InstrProfValueData VD3[] = {{(uint64_t) "callee1", 1}}; + Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr); + + Writer.addRecord(std::move(Record1)); + Writer.addRecord(std::move(Record2)); + Writer.addRecord(std::move(Record3)); + Writer.addRecord(std::move(Record4)); + + // Set big endian output. + const char *args[] = {"InstrProfTest", "-write-vp-data-in-big"}; + cl::ParseCommandLineOptions(sizeof(args) / sizeof(const char *), args); + ASSERT_EQ(support::big, InstrProfWriter::getValueProfDataEndianness()); + + auto Profile = Writer.writeBuffer(); + readProfile(std::move(Profile)); + + // Set big endian input. + Reader->setValueProfDataEndianness(support::big); + + ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234); + ASSERT_TRUE(NoError(R.getError())); + ASSERT_EQ(4U, R.get().getNumValueSites(IPVK_IndirectCallTarget)); + ASSERT_EQ(3U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); + ASSERT_EQ(0U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 1)); + ASSERT_EQ(2U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 2)); + ASSERT_EQ(1U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); + + std::unique_ptr<InstrProfValueData[]> VD = + R.get().getValueForSite(IPVK_IndirectCallTarget, 0); + ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3")); + ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2")); + ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1")); +} + } // end anonymous namespace |