[profiling] Do not instrument the End block

The End block is not necessarily the last one in the RPO. Iterate
until the end but skip the end block.

Bug: chromium:1381131
Change-Id: I5e1cd19c1b3bea4cbe565319631a7686ed2352fc
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4017313
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
Commit-Queue: Thibaud Michaud <thibaudm@chromium.org>
Cr-Commit-Position: refs/heads/main@{#84364}
This commit is contained in:
Thibaud Michaud 2022-11-17 12:49:50 +01:00 committed by V8 LUCI CQ
parent d741b80e58
commit 94d83955c4
2 changed files with 20 additions and 15 deletions

View File

@ -59,7 +59,7 @@ BasicBlockProfilerData* BasicBlockInstrumentor::Instrument(
AllowHandleDereference allow_handle_dereference;
// Skip the exit block in profiles, since the register allocator can't handle
// it and entry into it means falling off the end of the function anyway.
size_t n_blocks = schedule->RpoBlockCount() - 1;
size_t n_blocks = schedule->RpoBlockCount();
BasicBlockProfilerData* data = BasicBlockProfiler::Get()->NewData(n_blocks);
// Set the function name.
data->SetFunctionName(info->GetDebugName());
@ -99,6 +99,7 @@ BasicBlockProfilerData* BasicBlockInstrumentor::Instrument(
for (BasicBlockVector::iterator it = blocks->begin(); block_number < n_blocks;
++it, ++block_number) {
BasicBlock* block = (*it);
if (block == schedule->end()) continue;
// Iteration is already in reverse post-order.
DCHECK_EQ(block->rpo_number(), block_number);
data->SetBlockId(block_number, block->id().ToInt());
@ -146,10 +147,8 @@ BasicBlockProfilerData* BasicBlockInstrumentor::Instrument(
// The exit block is not instrumented and so we must ignore that block
// count.
if (block->control() == BasicBlock::kBranch &&
block->successors()[0]->rpo_number() !=
static_cast<int32_t>(n_blocks) &&
block->successors()[1]->rpo_number() !=
static_cast<int32_t>(n_blocks)) {
block->successors()[0] != schedule->end() &&
block->successors()[1] != schedule->end()) {
data->AddBranch(block->successors()[0]->id().ToInt(),
block->successors()[1]->id().ToInt());
}

View File

@ -61,13 +61,13 @@ TEST(ProfileDiamond) {
m.GenerateCode();
{
uint32_t expected[] = {0, 0, 0, 0, 0, 0};
uint32_t expected[] = {0, 0, 0, 0, 0, 0, 0};
m.Expect(arraysize(expected), expected);
}
m.Call(0);
{
uint32_t expected[] = {1, 1, 1, 0, 0, 1};
uint32_t expected[] = {1, 1, 1, 0, 0, 1, 0};
m.Expect(arraysize(expected), expected);
}
@ -75,28 +75,34 @@ TEST(ProfileDiamond) {
m.Call(1);
{
uint32_t expected[] = {1, 0, 0, 1, 1, 1};
uint32_t expected[] = {1, 0, 0, 1, 1, 1, 0};
m.Expect(arraysize(expected), expected);
}
m.Call(0);
{
uint32_t expected[] = {2, 1, 1, 1, 1, 2};
uint32_t expected[] = {2, 1, 1, 1, 1, 2, 0};
m.Expect(arraysize(expected), expected);
}
// Set the counters very high, to verify that they saturate rather than
// overflowing.
uint32_t near_overflow[] = {UINT32_MAX - 1, UINT32_MAX - 1, UINT32_MAX - 1,
UINT32_MAX - 1, UINT32_MAX - 1, UINT32_MAX - 1};
uint32_t near_overflow[] = {UINT32_MAX - 1,
UINT32_MAX - 1,
UINT32_MAX - 1,
UINT32_MAX - 1,
UINT32_MAX - 1,
UINT32_MAX - 1,
0};
m.SetCounts(arraysize(near_overflow), near_overflow);
m.Expect(arraysize(near_overflow), near_overflow);
m.Call(0);
m.Call(0);
{
uint32_t expected[] = {UINT32_MAX, UINT32_MAX, UINT32_MAX,
UINT32_MAX - 1, UINT32_MAX - 1, UINT32_MAX};
uint32_t expected[] = {
UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX - 1,
UINT32_MAX - 1, UINT32_MAX, 0};
m.Expect(arraysize(expected), expected);
}
}
@ -121,7 +127,7 @@ TEST(ProfileLoop) {
m.GenerateCode();
{
uint32_t expected[] = {0, 0, 0, 0, 0, 0};
uint32_t expected[] = {0, 0, 0, 0, 0, 0, 0};
m.Expect(arraysize(expected), expected);
}
@ -129,7 +135,7 @@ TEST(ProfileLoop) {
for (size_t i = 0; i < arraysize(runs); i++) {
m.ResetCounts();
CHECK_EQ(1, m.Call(static_cast<int>(runs[i])));
uint32_t expected[] = {1, runs[i] + 1, runs[i], runs[i], 1, 1};
uint32_t expected[] = {1, runs[i] + 1, runs[i], runs[i], 1, 1, 0};
m.Expect(arraysize(expected), expected);
}
}