While prof branch_weights inconsistencies are being fixed patch by patch (pass by pass) we need SwitchInstProfUpdateWrapper to be safe with respect to inconsistent metadata that can come from passes that have not been fixed yet. See the bug found by @nikic in D62126.
This patch introduces one more state (called Invalid) to the wrapper class that allows users to work with the underlying SwitchInst ignoring the prof metadata changes.
Created a unit test for the SwitchInstProfUpdateWrapper class.
Details
Diff Detail
- Repository
- rL LLVM
Event Timeline
llvm/lib/IR/Instructions.cpp | ||
---|---|---|
3907 ↗ | (On Diff #202166) | should we fix the underlying problem that leads to this inconsistent state? |
llvm/lib/IR/Instructions.cpp | ||
---|---|---|
3907 ↗ | (On Diff #202166) | That is what I'm trying to do. |
What I meant is that we should never see inconsistent state and instead of setting invalid state, we assert there. Ideally, the profile setting/update APIs should help user avoid creating the inconsistent state in the first place (i.e., catch the problem on the spot).
llvm/unittests/IR/InstructionsTest.cpp | ||
---|---|---|
797 ↗ | (On Diff #202166) | looks like exposing the raw interface to setMetadata for SI is not safe. Using wrapper interface can help catch error that leads to inconsistent state. |
813 ↗ | (On Diff #202166) | why it is not 39? |
llvm/include/llvm/IR/Instructions.h | ||
---|---|---|
3444 ↗ | (On Diff #202166) | Typo |
Yes. But in LLVM there are many places to fix. So we have to fix all of them at once and set the assertion here. The other option is to fix them one by one and tolerate such inconsistencies.
For example, SimplifyCFG is safe: it checks that the prof data is ok and only then makes its prof changes.
llvm/unittests/IR/InstructionsTest.cpp | ||
---|---|---|
797 ↗ | (On Diff #202166) | it is just a test and SI is just a SwitchInst. |
813 ↗ | (On Diff #202166) | That is because 39 was set when SIW was inconsistent. So SwitchInstProfUpdateWrapper::addCase() skipped setting the weight 39 and delegated addCase() to the underlying SwitchInst. The prof data attached to the underlying SwicthInst was kept intact and had 4 operands: 99, 11, 22, 33. So the next time we created a new wrapper it started with valid state. |
I suggest the following path:
- add an option to enforce internal error on inconsistency; by default the inconsistency is ignored.
- fix the exposed root cause one by one
- turn on the option by default
llvm/unittests/IR/InstructionsTest.cpp | ||
---|---|---|
797 ↗ | (On Diff #202166) | What I meant is that this kind of interface can be source of inconsistency. |
813 ↗ | (On Diff #202166) | Such interface behavior is not desirable. It is certainly surprising to the user which calls addCase as there is no way to know that the weight is ignored. |
@davidxl I believe the changes here are only temporary until D61179 lands, which will enforce this at the verifier level. As such I don't think there's much value in introducing a verification option here, because this is not really the right place to do that.
What I would suggest though is to maybe drop the branch weight metadata entirely if it's not valid. I think it's pretty weird (as was commented above) that you might end up with "valid" metadata after performing additional transformations (removing/adding cases), but that metadata will just be an accidental assignment, more or less. I think it would be better to discard it wholesale than risk an incorrect reinterpretation.
Ok. This option will probably simplify catching such bugs.
llvm/unittests/IR/InstructionsTest.cpp | ||
---|---|---|
813 ↗ | (On Diff #202166) | In future there will be no inconsistent states allowed and I suggest that the users write their code as if the stae is always consistent. During the transition period we just propagate the Undefined Behavior related to the prof data. |
added option switch-inst-prof-update-wrapper-strict to assert if prof data is inconsistent. It is off by default.
Probably it makes sense to enable prof branch_weights validation (patch D61179) in the same way.
once the cleanup is done, the state tracking should be removed as well.
llvm/lib/IR/Instructions.cpp | ||
---|---|---|
48 ↗ | (On Diff #202393) | typo: Strinct |
llvm/lib/IR/Instructions.cpp | ||
---|---|---|
48 ↗ | (On Diff #202393) | also typo: Swicth, var name and in the cl::desc below. |
lgtm assuming the state tracking code gets removed (or put under NDEBUG in some way) after the cleanup.