I was seeing a regression when enabling FS discriminators on an non-FS CSSPGO build. This is because a probe can get a zero-valued discriminator at a specific pass and that could lead to accidentally loading the corresponding base counter in the non-FS profile, while a non-zeo discriminator would end up getting zero samples. This could in turn undo the sample distribution effort done by previous BFI maintenance work and the probe distribution factor work for pseudo probes specifically. To mitigate that I'm disabling loading a non-FS profile against FS discriminators. The problem should also exist with non-CS AutoFDO, so I'm doing this for it too.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
@xur wondering if you have seen such regression for non-CS AutoFDO. I think in theory it could be there but I never measured that.
I was seeing a regression when enabling FS discriminators on an non-FS CSSPGO build. This is because a probe can get a zero-valued discriminator at a specific pass and that could lead to accidentally loading the corresponding base counter in the non-FS profile
For non-FS profile, probe doesn't have discriminator, is there no way to differentiate zero discriminator from no discriminator? If a probe in the profile doesn't have discriminator, it should not be considered for FS profile loading. In this case, if input profile is not FS, no probe would have discriminator, hence nothing should be loaded in MIR. Is such checking missing on per-probe level?
llvm/lib/CodeGen/MIRSampleProfile.cpp | ||
---|---|---|
297 | The profile itself isn't really invalid, it's just not suitable for FS loading, so piggyback on ProfileIsValid seems hacky. Suggest to have a more dedicated way to skip. Also please add comment to explain why only FS enabled profile is accepted for MIR loading. |
The body sample map uses id+discriminator as the key, so currently we don't have a way on the function level to tell if a function profile is FS or not. We can tell on the program level, basically using the FS flag.
So the situation here is that the input profile isn't FS, but the current build has FS flag on. Now at MIR profile loading, we get the line+FSdiscriminator from IR, and trying to look up BodySamples map via findSamplesAt. How does that end up with base profile given the findSamplesAt has line+FSdiscriminator as key, which is from DIL on IR. When input profile is not FS, I assume the difference (comparing to when input profile is FS) is that the matching line+FSdiscriminator won't exist in BodySamples, hence it will find and load nothing for that location?
Yes, most of the cases the lines will end up loading nothing, and the sample loader doesn't do anything further in terms of annotation and inference (https://github.com/llvm/llvm-project/blob/516e301752560311d2cd8c2b549493eb0f98d01b/llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h#L877). However for lines that do have a zero FSdiscriminator, line+FSdiscriminator can accidentally match the base counter while all other lines still load nothing. This creates a situation only a few blocks in a function have samples from their base counter while all other blocks will have a zero count. Inferencing from there will be problematic.
However for lines that do have a zero FSdiscriminator, line+FSdiscriminator can accidentally match the base counter while all other lines still load nothing.
Can this also happen when input profile is actually a FS profile? which is also not good? Or is that less of a problem when input profile is FS because we will also load other samples whose FSDiscriminator is non-zero?
I think it's not a problem for FS profiles. Given a FS profile, a zero discriminator is a valid FS discriminator which means the counter is not aggregated and there will be no more than one line loading that counter on MIR. For a non-FS profile, we cannot tell if a zero is a valid FS discriminator unless the file-level flag is checked.
ok, that makes sense since profile reader actually masks discriminator based on the current FSDiscriminator mask.
Moving check from doInitialization into runOnFunction since the former doesn't stop MIRProfileLoader which is a function pass from continuing.
The profile itself isn't really invalid, it's just not suitable for FS loading, so piggyback on ProfileIsValid seems hacky. Suggest to have a more dedicated way to skip.
Also please add comment to explain why only FS enabled profile is accepted for MIR loading.