A constant pointer in a non-volatile alias set (e.g., null) may be used by volatile accesses. For such cases, we might should bail out instead of asserting. This should fix PR25628.
Contributed-by: Ed Baunton
Differential D16986
[LICM] Don't assert on volatile accesses mssimpso on Feb 8 2016, 7:33 AM. Authored by
Details
Diff Detail Event TimelineComment Actions Thanks Matt. After I created this patch, I actually did some more investigation with Nuno Lopes where we discovered that there is a more subtle bug seemingly going on with the alias analysis that occurs in tbaa. Running the alias analysis without tbaa produces 2 alias sets, while with tbaa it (seemingly erroneously) produces a third alias set. The upshot is, that the AST that is checked a few lines up in this file returns isVolatile as false because it is checking a third set. I spent a few hours yesterday trying to track how this magical third set gets produced in the tbaa code and the AliasAnalysis code in general but couldn't get to the bottom of it. As it is, this patch *I think* will fix the assertion at hand in a relatively safe way: the isSimple already checks isVolatile and bails the optimisation if that is the case (rather than assertion). The full fix would be to adjust tbaa to stop producing this third spurious alias set (if that is the case). tldr; not sure this is a really good fix. Comment Actions Also that test case can be reduced more by using the one that was posted on the bug originally. Comment Actions Ed, It's not surprising to me that TBAA would produce more precise results (and thus an additional alias set in this case). The essential piece is that, in the test case, it's claiming that the address of b cannot be null, which is correct I think. That allows LICM to remove load2 and change load3 to load from null. The alias set containing null cannot be marked volatile since it doesn't contain any loads or stores. But now null is used by load3, which is volatile. So your original patch sounded like a reasonable solution to me! Hopefully someone more knowledgeable will chime in. In your patch, the check for isVolatile is done in IsUnordered. Comment Actions Seems like both isSimple and isUnordered check for volatility: http://llvm.org/docs/doxygen/html/Instructions_8h_source.html#l00281 ? Comment Actions Another option would be to adjust the AliasSetTracker's add method to check if any of the users of the instruction are volatile and then mark the set as as volatile (currently it only checks if the instruction itself is volatile before marking the set as volatile). This would be a bit more inefficient as you would have to loop for every user of every load and store added to the set but it would mean no change to the LICM logic... I am not sure which is more correct. Comment Actions Regarding the potential AST modification: loads from null or stores to it are not legal. The original testcase isn't legal either (it contains a dereference of an uninitialized pointer). While the compiler should not abort on any code, we should not be making special accommodations for handling such situations that could negatively affect legal cases. Comment Actions The changes to LICM in this patch are almost certainly not the right approach. The removed assertions give a good hint on where to look; this is likely an AliasSetTracker bug. p.s. Finding another test case which doesn't involve UB - even just using a non-zero address space - would be good. Comment Actions This response hits the nail on the head. If you have a alias set which is being read from with a volatile load which isn't marked volatile, that's the bug you need to fix. Comment Actions I'm abandoning this change due to feedback from Philip and Krzysztof suggesting it's probably not the right approach. Ed, please feel free to continue investigating this issue if it interests you. Thanks. Comment Actions Just a quick comment on this bug. We can see it from two angles:
I'm personally more favorable of 2), since I don't think it's worth to mess with volatile stuff, since it can be dangerous for applications and probably there isn't much performance to gain there. Comment Actions I disagree with your framing. Unless I misunderstood the issue, this is a clear bug in AST regardless of what TBAA returns for aliasing information. If we ended up with a volatile memory access being part of a alias set, that alias set *must* be marked volatile. It's okay to have non-volatile accesses as part of the volatile set, but not the other way around. If we required the isVolatile flag to be precise for all elements in the set, we'd essentially be requiring alias analysis to *always* get a precise no-alias result when it's possible to do so. That's not an invariant we can uphold. Comment Actions One of the alias set is not being marked as volatile because TBAA decides it cannot possibly alias with the volatile alias set (because of the UB). But then store forwarding happens and LICM realizes (or doesn't) that two of the alias sets that were said to be disjoint by TBAA in fact alias. So I believe my analysis is correct. It's the fact that TBAA decides that two pointers don't alias and therefore only one of the sets gets marked as volatile. Comment Actions Can you clarify this point? AFAIK, LICM does not do store forwarding. How did store forwarding come into the picture at all? Also, if we ever discover two pointers mustalias, then by definition they must be the same alias set. If not, we have constructed *invalid, and incorrect* alias sets. Oh, I think I see the problem. You're saying that they're both noalias and mustalias discovered through two different mechanism. Ouch, ouch, ouch. Comment Actions It does. see here: http://www.llvm.org/docs/doxygen/html/LICM_8cpp_source.html#l00790
If you add UB to the picture, then 2 pointers that must alias may end up in different alias sets. That's ok; it's just LICM doesn't know how to handle this specific volatile case. I second my case that we should change TBAA instead, such that it handles volatile stuff more conservatively. Comment Actions "I second my case that we should change TBAA instead, such that it handles Volatileness and aliasing are different properties. The volatileness of a given access is something the optimizer needs to take (and yes, you can get completely inconsistent results between different TL;DR You should fix LICM or AST, depending on your viewpoint. Only one result is "most correct" at the language semantic level, but both (apropos of nothing, the lack of transitivity/etc in TBAA is one of the Comment Actions I agree with your points. |