This is an archive of the discontinued LLVM Phabricator instance.

[llvm-profgen] Fix bug of setting function entry
ClosedPublic

Authored by wlei on Nov 9 2021, 9:01 AM.

Details

Summary

Previously we set isFuncEntry flag to true when the funcName from DWARF is equal to the name in symbol table and we use this flag to ignore reporting callsite sample that's from an intra func branch. However, in HHVM, it appears that the symbol table name is inconsistent with the dwarf info func name, it's likely due to OptimizeGlobalAliases.

This change is a workaround in llvm-profgen side to mark the only one range as the function entry and add warnings for the remaining inconsistence.

This also fixed a missing getCanonicalFnName for symbol name which caused the mismatching as well.

Diff Detail

Event Timeline

wlei created this revision.Nov 9 2021, 9:01 AM
wlei requested review of this revision.Nov 9 2021, 9:01 AM
Herald added a project: Restricted Project. · View Herald TranscriptNov 9 2021, 9:01 AM
wlei edited the summary of this revision. (Show Details)Nov 9 2021, 9:28 AM
wlei added reviewers: hoy, wenlei.
wenlei added a comment.Nov 9 2021, 9:41 AM

However, in HHVM, I found that there are many functions that none of their ranges is set to true

Why is this happening? Should we fix this so that for any function, there's always one range that is considered entry?

wlei added a comment.Nov 9 2021, 12:07 PM

However, in HHVM, I found that there are many functions that none of their ranges is set to true

Why is this happening? Should we fix this so that for any function, there's always one range that is considered entry?

For example, in HHVM:
The DWARF function name is "_ZN8facebook6falcon10ProcessKeyC2ERKS1_" and the same start address on ELF the symbol name is " _ZN8facebook6falcon10ProcessKeyC1ERKS1_". The function has only one range.

So there is name difference between DWARF and symbol table even it has only one range. I don't know the root reason for debug info, maybe some change in FE

Should we fix this so that for any function, there's always one range that is considered entry?

I'm thinking a case even we make the function entry flag correct, there's still a chance to call a non-entry function that should report the count, like "main" --> "foo.V1" , maybe foo.V1 is the function slice covering function start.

See the change in this patch, try to remove the isFuncEntry logic. Instead, we check if the source and start' range is from the same function but different split range.

hoy added inline comments.Nov 9 2021, 12:37 PM
llvm/tools/llvm-profgen/ProfileGenerator.cpp
419 ↗(On Diff #385845)

Can this filter out non-entry jumps that is from a different function to an outlined part of a function? I.e the Coro resume case

wenlei added a comment.Nov 9 2021, 2:50 PM

However, in HHVM, I found that there are many functions that none of their ranges is set to true

Why is this happening? Should we fix this so that for any function, there's always one range that is considered entry?

For example, in HHVM:
The DWARF function name is "_ZN8facebook6falcon10ProcessKeyC2ERKS1_" and the same start address on ELF the symbol name is " _ZN8facebook6falcon10ProcessKeyC1ERKS1_". The function has only one range.

So there is name difference between DWARF and symbol table even it has only one range. I don't know the root reason for debug info, maybe some change in FE

Should we fix this so that for any function, there's always one range that is considered entry?

I'm thinking a case even we make the function entry flag correct, there's still a chance to call a non-entry function that should report the count, like "main" --> "foo.V1" , maybe foo.V1 is the function slice covering function start.

That shouldn't happen. Function calls has to go through prolog, and we shouldn't expect to see cross-function transfer in the middle of a function without going through prolog.

See the change in this patch, try to remove the isFuncEntry logic. Instead, we check if the source and start' range is from the same function but different split range.

wlei updated this revision to Diff 386063.Nov 9 2021, 10:23 PM

Updating D113492: [llvm-profgen] Fix bug of split range branch sample

wlei added a comment.Nov 9 2021, 10:24 PM

That shouldn't happen. Function calls has to go through prolog, and we shouldn't expect to see cross-function transfer in the middle of a function without going through prolog.

That makes sense. Abandon this patch, reverted to previous version.

update to mark the only range in the function as the entry and warn if no entry range exists.

llvm/tools/llvm-profgen/ProfileGenerator.cpp
419 ↗(On Diff #385845)

I see, it can't, abandon this patch, reverted to previous version.

wlei added a comment.Nov 9 2021, 10:28 PM

Update the statistics summary of HHVM:

Before the num of function has no entry:

1.82%(5687/312230) of functions have no entry range!

After fix to mark the only range as entry:

0.12%(383/312230) of functions have no entry range!
hoy added inline comments.Nov 10 2021, 11:01 PM
llvm/tools/llvm-profgen/ProfiledBinary.cpp
356

Can the flag be set here based on FuncRange->Func->Ranges.size() == 1 instead?

wlei updated this revision to Diff 386552.Nov 11 2021, 9:46 AM

add getCanonicalFnName for symbol name
move setIsFuncEntry in front of dissassembleSymbol in case there're alias symbol
addressing Hongtao's feedback

llvm/tools/llvm-profgen/ProfiledBinary.cpp
356

This is better place, thanks for the suggestion!

The change description needs to be updated too.

llvm/tools/llvm-profgen/ProfiledBinary.cpp
177

This warning is a bit confusing.. Technically there's no such thing as function doesn't have an entry. How about this: Failed to determine function entry for xxx due to inconsistent name from symbol table and dwarf info.

382–383

Moving this check is for printing symbols with zero size, right?

What symbols have zero size?

wlei added inline comments.Nov 11 2021, 10:46 AM
llvm/tools/llvm-profgen/ProfiledBinary.cpp
382–383

Yes, all is due to the alias issues. Those are two type: 1)C1 vs C2 2) undemangled symbol

zero-size: _ZN5boost6threadC1Ev
<_ZN5boost6threadC2Ev>:
zero-size: numa_set_membind_v2
<numa_set_membind_v2_int>:

See they are all right followed by their non-zero size alias.

But but not vice versa, remembering one of C1 or C2 can't be removed.

hoy added inline comments.Nov 11 2021, 11:19 AM
llvm/tools/llvm-profgen/ProfiledBinary.cpp
382–383

On the second thought, what does this check do? I thought symbols are sorted based on their start offset before disassembled.

wlei updated this revision to Diff 386625.Nov 11 2021, 12:35 PM

Updating D113492: [llvm-profgen] Fix bug of split range branch sample

llvm/tools/llvm-profgen/ProfiledBinary.cpp
177

Thanks for the suggestions!

382–383

I see, this check is no need then,

wlei retitled this revision from [llvm-profgen] Fix bug of split range branch sample to [llvm-profgen] Fix bug of setting function entry.Nov 11 2021, 1:43 PM
wlei edited the summary of this revision. (Show Details)
hoy accepted this revision.Nov 11 2021, 3:15 PM

lgtm, thanks.

This revision is now accepted and ready to land.Nov 11 2021, 3:15 PM
wenlei accepted this revision.Nov 11 2021, 5:18 PM

lgtm, thanks.

This revision was automatically updated to reflect the committed changes.