Skip to content

Commit

Permalink
[nfc][InstrProfTest]Add a test fixture to parameterize the read-write…
Browse files Browse the repository at this point in the history
… test of value profiles (#73038)

This patch factor out the common code among three similar test cases.
The input data and test logic are pretty similar. Parameterize the
differences (prof-weight and endianness) as advised in
#72611.
- Remove duplicated tests
  • Loading branch information
minglotus-6 committed Nov 21, 2023
1 parent cc21287 commit 2743b30
Showing 1 changed file with 49 additions and 104 deletions.
153 changes: 49 additions & 104 deletions llvm/unittests/ProfileData/InstrProfTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,25 @@ struct SparseInstrProfTest : public InstrProfTest {
void SetUp() override { Writer.setOutputSparse(true); }
};

struct InstrProfReaderWriterTest
: public InstrProfTest,
public ::testing::WithParamInterface<
std::tuple<bool, uint64_t, llvm::endianness>> {
void SetUp() override { Writer.setOutputSparse(std::get<0>(GetParam())); }
void TearDown() override {
// Reset writer value profile data endianness after each test case. Note
// it's not necessary to reset reader value profile endianness for each test
// case. Each test case creates a new reader; at reader initialization time,
// it uses the endianness from hash table object (which is little by
// default).
Writer.setValueProfDataEndianness(llvm::endianness::little);
}

uint64_t getProfWeight() const { return std::get<1>(GetParam()); }

llvm::endianness getEndianness() const { return std::get<2>(GetParam()); }
};

struct MaybeSparseInstrProfTest : public InstrProfTest,
public ::testing::WithParamInterface<bool> {
void SetUp() override { Writer.setOutputSparse(GetParam()); }
Expand Down Expand Up @@ -640,7 +659,7 @@ static const char callee4[] = "callee4";
static const char callee5[] = "callee5";
static const char callee6[] = "callee6";

TEST_P(MaybeSparseInstrProfTest, get_icall_data_read_write) {
TEST_P(InstrProfReaderWriterTest, icall_data_read_write) {
NamedInstrProfRecord Record1("caller", 0x1234, {1, 2});

// 4 value sites.
Expand All @@ -655,35 +674,51 @@ TEST_P(MaybeSparseInstrProfTest, get_icall_data_read_write) {
InstrProfValueData VD3[] = {{(uint64_t)callee1, 1}};
Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);

Writer.addRecord(std::move(Record1), Err);
Writer.addRecord(std::move(Record1), getProfWeight(), Err);
Writer.addRecord({"callee1", 0x1235, {3, 4}}, Err);
Writer.addRecord({"callee2", 0x1235, {3, 4}}, Err);
Writer.addRecord({"callee3", 0x1235, {3, 4}}, Err);

// Set writer value prof data endianness.
Writer.setValueProfDataEndianness(getEndianness());

auto Profile = Writer.writeBuffer();
readProfile(std::move(Profile));

// Set reader value prof data endianness.
Reader->setValueProfDataEndianness(getEndianness());

Expected<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
EXPECT_THAT_ERROR(R.takeError(), Succeeded());
ASSERT_THAT_ERROR(R.takeError(), Succeeded());
ASSERT_EQ(4U, R->getNumValueSites(IPVK_IndirectCallTarget));
ASSERT_EQ(3U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
ASSERT_EQ(0U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
ASSERT_EQ(2U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
ASSERT_EQ(1U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
EXPECT_EQ(3U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
EXPECT_EQ(0U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
EXPECT_EQ(2U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
EXPECT_EQ(1U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3));

uint64_t TotalC;
std::unique_ptr<InstrProfValueData[]> VD =
R->getValueForSite(IPVK_IndirectCallTarget, 0, &TotalC);

ASSERT_EQ(3U, VD[0].Count);
ASSERT_EQ(2U, VD[1].Count);
ASSERT_EQ(1U, VD[2].Count);
ASSERT_EQ(6U, TotalC);
EXPECT_EQ(3U * getProfWeight(), VD[0].Count);
EXPECT_EQ(2U * getProfWeight(), VD[1].Count);
EXPECT_EQ(1U * getProfWeight(), VD[2].Count);
EXPECT_EQ(6U * getProfWeight(), TotalC);

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"));
EXPECT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3"));
EXPECT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2"));
EXPECT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1"));
}

INSTANTIATE_TEST_SUITE_P(
WeightAndEndiannessTest, InstrProfReaderWriterTest,
::testing::Combine(
::testing::Bool(), /* Sparse */
::testing::Values(1U, 10U), /* ProfWeight */
::testing::Values(llvm::endianness::big,
llvm::endianness::little) /* Endianness */
));

TEST_P(MaybeSparseInstrProfTest, annotate_vp_data) {
NamedInstrProfRecord Record("caller", 0x1234, {1, 2});
Record.reserveSites(IPVK_IndirectCallTarget, 1);
Expand Down Expand Up @@ -780,96 +815,6 @@ TEST_P(MaybeSparseInstrProfTest, annotate_vp_data) {
ASSERT_EQ(1U, ValueData[3].Count);
}

TEST_P(MaybeSparseInstrProfTest, get_icall_data_read_write_with_weight) {
NamedInstrProfRecord Record1("caller", 0x1234, {1, 2});

// 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), 10, Err);
Writer.addRecord({"callee1", 0x1235, {3, 4}}, Err);
Writer.addRecord({"callee2", 0x1235, {3, 4}}, Err);
Writer.addRecord({"callee3", 0x1235, {3, 4}}, Err);
auto Profile = Writer.writeBuffer();
readProfile(std::move(Profile));

Expected<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
EXPECT_THAT_ERROR(R.takeError(), Succeeded());
ASSERT_EQ(4U, R->getNumValueSites(IPVK_IndirectCallTarget));
ASSERT_EQ(3U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
ASSERT_EQ(0U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
ASSERT_EQ(2U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
ASSERT_EQ(1U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3));

uint64_t TotalC;
std::unique_ptr<InstrProfValueData[]> VD =
R->getValueForSite(IPVK_IndirectCallTarget, 0, &TotalC);
ASSERT_EQ(30U, VD[0].Count);
ASSERT_EQ(20U, VD[1].Count);
ASSERT_EQ(10U, VD[2].Count);
ASSERT_EQ(60U, TotalC);

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"));
}

TEST_P(MaybeSparseInstrProfTest, get_icall_data_read_write_big_endian) {
NamedInstrProfRecord Record1("caller", 0x1234, {1, 2});

// 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), Err);
Writer.addRecord({"callee1", 0x1235, {3, 4}}, Err);
Writer.addRecord({"callee2", 0x1235, {3, 4}}, Err);
Writer.addRecord({"callee3", 0x1235, {3, 4}}, Err);

// Set big endian output.
Writer.setValueProfDataEndianness(llvm::endianness::big);

auto Profile = Writer.writeBuffer();
readProfile(std::move(Profile));

// Set big endian input.
Reader->setValueProfDataEndianness(llvm::endianness::big);

Expected<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
EXPECT_THAT_ERROR(R.takeError(), Succeeded());
ASSERT_EQ(4U, R->getNumValueSites(IPVK_IndirectCallTarget));
ASSERT_EQ(3U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
ASSERT_EQ(0U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
ASSERT_EQ(2U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
ASSERT_EQ(1U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3));

std::unique_ptr<InstrProfValueData[]> VD =
R->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(llvm::endianness::little);
}

TEST_P(MaybeSparseInstrProfTest, get_icall_data_merge1) {
static const char caller[] = "caller";
NamedInstrProfRecord Record11(caller, 0x1234, {1, 2});
Expand Down

0 comments on commit 2743b30

Please sign in to comment.