This is an archive of the discontinued LLVM Phabricator instance.

[PGO] incorrect classof in InstrProfIncrementInst
ClosedPublic

Authored by KuiChou on Jan 12 2023, 1:10 AM.

Details

Summary

Class InstrProfIncrementInstStep inherits from InstrProfIncrementInst but cannot cast to InstrProfIncrementInst, because InstrProfIncrementInst::classof does not cover such circumstance。

Function InstrProfiling::run traverse all instruction in a module and try to cast them to InstrProfIncrementInst using dyn_cast, but it will return nullptr if the instruction is InstrProfIncrementInstStep(subclass of InstrProfIncrementInst).

Diff Detail

Event Timeline

KuiChou created this revision.Jan 12 2023, 1:10 AM
Herald added a project: Restricted Project. · View Herald TranscriptJan 12 2023, 1:10 AM
Herald added subscribers: ellis, wenlei. · View Herald Transcript
KuiChou requested review of this revision.Jan 12 2023, 1:10 AM

Can you upload with full context? Either use Arcanist or follow instructions here: https://llvm.org/docs/Phabricator.html#requesting-a-review-via-the-web-interface

Thanks!

ellis accepted this revision.Jan 12 2023, 9:41 AM

Ah, I see the dyn_cast you are talking about is here. I think this is only a problem if InstrProfIncrementInstStep is the only InstrProf instruction in a function and it has an llvm.instrprof.value.profile instruction, which explains why we didn't catch this bug for so long. In that case, the later call to getOrCreateRegionCounters() will be skipped and, according to the comment, this is required for value profiling. Is that what you observed? If so it should be easy to add a small test case, probably similar to llvm/test/Instrumentation/InstrProfiling/early-exit.ll, but this could be followed up in another patch. Thanks for fixing!

This revision is now accepted and ready to land.Jan 12 2023, 9:41 AM
tejohnson requested changes to this revision.Jan 12 2023, 9:50 AM

Ah, I see the dyn_cast you are talking about is here. I think this is only a problem if InstrProfIncrementInstStep is the only InstrProf instruction in a function and it has an llvm.instrprof.value.profile instruction, which explains why we didn't catch this bug for so long. In that case, the later call to getOrCreateRegionCounters() will be skipped and, according to the comment, this is required for value profiling. Is that what you observed? If so it should be easy to add a small test case, probably similar to llvm/test/Instrumentation/InstrProfiling/early-exit.ll, but this could be followed up in another patch. Thanks for fixing!

Why not include the suggested test in this patch?

This revision now requires changes to proceed.Jan 12 2023, 9:50 AM
ellis added a comment.Jan 12 2023, 9:56 AM

Ah, I see the dyn_cast you are talking about is here. I think this is only a problem if InstrProfIncrementInstStep is the only InstrProf instruction in a function and it has an llvm.instrprof.value.profile instruction, which explains why we didn't catch this bug for so long. In that case, the later call to getOrCreateRegionCounters() will be skipped and, according to the comment, this is required for value profiling. Is that what you observed? If so it should be easy to add a small test case, probably similar to llvm/test/Instrumentation/InstrProfiling/early-exit.ll, but this could be followed up in another patch. Thanks for fixing!

Why not include the suggested test in this patch?

You're right. I suppose fewer patches is better and I think it should be an easy test to add.

Ah, I see the dyn_cast you are talking about is here. I think this is only a problem if InstrProfIncrementInstStep is the only InstrProf instruction in a function and it has an llvm.instrprof.value.profile instruction, which explains why we didn't catch this bug for so long. In that case, the later call to getOrCreateRegionCounters() will be skipped and, according to the comment, this is required for value profiling. Is that what you observed? If so it should be easy to add a small test case, probably similar to llvm/test/Instrumentation/InstrProfiling/early-exit.ll, but this could be followed up in another patch. Thanks for fixing!

Yes. But even if InstrProfIncrementInstStep is the only InstrProf instruction in a function, getOrCreateRegionCounters will still be called through InstrProfiling::run -> lowerIntrinsics -> lowerIncrement -> getCounterAddress -> getOrCreateRegionCounters. So, to reproduce this problem, we should satisfy two conditions:

  1. InstrProfIncrementInstStep is the only InstrProf instruction in a function and it has InstrProfValueProfileInst instruction
  2. InstrProfValueProfileInst must be in front of InstrProfIncrementInstStep instruction

PGO will always generate an InstrProfIncrementInst instruction in the front of a function so normally, this bug cannot happen

KuiChou updated this revision to Diff 489709.Jan 16 2023, 11:07 PM

add test case

Thanks for adding a test, couple questions below, but generally lgtm.

Ah, I see the dyn_cast you are talking about is here. I think this is only a problem if InstrProfIncrementInstStep is the only InstrProf instruction in a function and it has an llvm.instrprof.value.profile instruction, which explains why we didn't catch this bug for so long. In that case, the later call to getOrCreateRegionCounters() will be skipped and, according to the comment, this is required for value profiling. Is that what you observed? If so it should be easy to add a small test case, probably similar to llvm/test/Instrumentation/InstrProfiling/early-exit.ll, but this could be followed up in another patch. Thanks for fixing!

Yes. But even if InstrProfIncrementInstStep is the only InstrProf instruction in a function, getOrCreateRegionCounters will still be called through InstrProfiling::run -> lowerIntrinsics -> lowerIncrement -> getCounterAddress -> getOrCreateRegionCounters. So, to reproduce this problem, we should satisfy two conditions:

  1. InstrProfIncrementInstStep is the only InstrProf instruction in a function and it has InstrProfValueProfileInst instruction

I assume this should be "is the only InstrProfIncrement instruction" (since there is another InstrProf instruction in the function (InstrProfValueProfileInst)?

  1. InstrProfValueProfileInst must be in front of InstrProfIncrementInstStep instruction

PGO will always generate an InstrProfIncrementInst instruction in the front of a function so normally, this bug cannot happen

Out of curiosity, how was this encountered?

llvm/test/Instrumentation/InstrProfiling/before-value-profile-lowering.ll
1 ↗(On Diff #489709)

s/genereated/generated/

Also, suggest expanding the comment to clarify the exact scenario being tested, e.g. something like: ", when the only instrprof increment is a step instruction following a value profile instruction."

Thanks for adding a test, couple questions below, but generally lgtm.

Ah, I see the dyn_cast you are talking about is here. I think this is only a problem if InstrProfIncrementInstStep is the only InstrProf instruction in a function and it has an llvm.instrprof.value.profile instruction, which explains why we didn't catch this bug for so long. In that case, the later call to getOrCreateRegionCounters() will be skipped and, according to the comment, this is required for value profiling. Is that what you observed? If so it should be easy to add a small test case, probably similar to llvm/test/Instrumentation/InstrProfiling/early-exit.ll, but this could be followed up in another patch. Thanks for fixing!

Yes. But even if InstrProfIncrementInstStep is the only InstrProf instruction in a function, getOrCreateRegionCounters will still be called through InstrProfiling::run -> lowerIntrinsics -> lowerIncrement -> getCounterAddress -> getOrCreateRegionCounters. So, to reproduce this problem, we should satisfy two conditions:

  1. InstrProfIncrementInstStep is the only InstrProf instruction in a function and it has InstrProfValueProfileInst instruction

I assume this should be "is the only InstrProfIncrement instruction" (since there is another InstrProf instruction in the function (InstrProfValueProfileInst)?

  1. InstrProfValueProfileInst must be in front of InstrProfIncrementInstStep instruction

PGO will always generate an InstrProfIncrementInst instruction in the front of a function so normally, this bug cannot happen

Out of curiosity, how was this encountered?

  1. Yes, you are right. It should be "InstrProfIncrementInstStep is the only InstrProfIncrement instruction in a function and it has InstrProfValueProfileInst instruction"
  2. I have been trying to implement function reordering in LLVM PGO which will modify current PGO code, this cause a bug in my code.
KuiChou updated this revision to Diff 490023.Jan 17 2023, 7:42 PM

update test case

This revision is now accepted and ready to land.Jan 17 2023, 7:49 PM
ellis added a comment.Jan 18 2023, 4:29 PM

Thanks for adding a test, couple questions below, but generally lgtm.

Ah, I see the dyn_cast you are talking about is here. I think this is only a problem if InstrProfIncrementInstStep is the only InstrProf instruction in a function and it has an llvm.instrprof.value.profile instruction, which explains why we didn't catch this bug for so long. In that case, the later call to getOrCreateRegionCounters() will be skipped and, according to the comment, this is required for value profiling. Is that what you observed? If so it should be easy to add a small test case, probably similar to llvm/test/Instrumentation/InstrProfiling/early-exit.ll, but this could be followed up in another patch. Thanks for fixing!

Yes. But even if InstrProfIncrementInstStep is the only InstrProf instruction in a function, getOrCreateRegionCounters will still be called through InstrProfiling::run -> lowerIntrinsics -> lowerIncrement -> getCounterAddress -> getOrCreateRegionCounters. So, to reproduce this problem, we should satisfy two conditions:

  1. InstrProfIncrementInstStep is the only InstrProf instruction in a function and it has InstrProfValueProfileInst instruction

I assume this should be "is the only InstrProfIncrement instruction" (since there is another InstrProf instruction in the function (InstrProfValueProfileInst)?

  1. InstrProfValueProfileInst must be in front of InstrProfIncrementInstStep instruction

PGO will always generate an InstrProfIncrementInst instruction in the front of a function so normally, this bug cannot happen

Out of curiosity, how was this encountered?

  1. Yes, you are right. It should be "InstrProfIncrementInstStep is the only InstrProfIncrement instruction in a function and it has InstrProfValueProfileInst instruction"
  2. I have been trying to implement function reordering in LLVM PGO which will modify current PGO code, this cause a bug in my code.

That's funny because I am also working on extending LLVM PGO to instrument function timestamps which will be used to reorder functions for optimization. I assume this is similar to what you are working on? I'm hoping to send up an RFC to https://discourse.llvm.org/ soon so please be on the lookout for that.

This comment was removed by KuiChou.

Thanks for adding a test, couple questions below, but generally lgtm.

Ah, I see the dyn_cast you are talking about is here. I think this is only a problem if InstrProfIncrementInstStep is the only InstrProf instruction in a function and it has an llvm.instrprof.value.profile instruction, which explains why we didn't catch this bug for so long. In that case, the later call to getOrCreateRegionCounters() will be skipped and, according to the comment, this is required for value profiling. Is that what you observed? If so it should be easy to add a small test case, probably similar to llvm/test/Instrumentation/InstrProfiling/early-exit.ll, but this could be followed up in another patch. Thanks for fixing!

Yes. But even if InstrProfIncrementInstStep is the only InstrProf instruction in a function, getOrCreateRegionCounters will still be called through InstrProfiling::run -> lowerIntrinsics -> lowerIncrement -> getCounterAddress -> getOrCreateRegionCounters. So, to reproduce this problem, we should satisfy two conditions:

  1. InstrProfIncrementInstStep is the only InstrProf instruction in a function and it has InstrProfValueProfileInst instruction

I assume this should be "is the only InstrProfIncrement instruction" (since there is another InstrProf instruction in the function (InstrProfValueProfileInst)?

  1. InstrProfValueProfileInst must be in front of InstrProfIncrementInstStep instruction

PGO will always generate an InstrProfIncrementInst instruction in the front of a function so normally, this bug cannot happen

Out of curiosity, how was this encountered?

  1. Yes, you are right. It should be "InstrProfIncrementInstStep is the only InstrProfIncrement instruction in a function and it has InstrProfValueProfileInst instruction"
  2. I have been trying to implement function reordering in LLVM PGO which will modify current PGO code, this cause a bug in my code.

That's funny because I am also working on extending LLVM PGO to instrument function timestamps which will be used to reorder functions for optimization. I assume this is similar to what you are working on?

Oh that's great! What's I'm working on is to reorder functions through function call graph and call times. It's still in progress.

I'm hoping to send up an RFC to https://discourse.llvm.org/ soon so please be on the lookout for that.

OK. I'll keep an eye on it.

KuiChou updated this revision to Diff 490435.Jan 19 2023, 2:55 AM

fix test error

Thank you for the reviews! Could one of you commit this revision for me as I do not have commit access?

ellis added a comment.Jan 20 2023, 9:56 AM

Thank you for the reviews! Could one of you commit this revision for me as I do not have commit access?

Sure I can commit this today.

This revision was landed with ongoing or failed builds.Jan 20 2023, 10:22 AM
This revision was automatically updated to reflect the committed changes.