This is similar to D94106, but for the isGuaranteedToTransferExecutionToSuccessor() helper. We should not assume that readonly functions will return, as this is only true for mustprogress functions (in which case we already infer willreturn). As with the DCE change, for now continue assuming that readonly intrinsics will return, as not all target intrinsics have been annotated yet.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
LGTM, thanks
lib/Analysis/ValueTracking.cpp | ||
---|---|---|
5059 ↗ | (On Diff #318761) | I guess we could incorporate the argmemonly reasoning in 'FunctionAttrs`, using something like argmemonly + nosync => willreturn, assuming that IO can only happen through inaccessible memory? Just argmemonly would not be enough I think, because we still need to rule out volatile accesses/synchronization via. the arguments. |
unittests/Analysis/ValueTrackingTest.cpp | ||
654 ↗ | (On Diff #318761) | also add // call void @unknown(i32* %p) willreturn? |
lib/Analysis/ValueTracking.cpp | ||
---|---|---|
5059 ↗ | (On Diff #318761) | Yeah, I agree that mustprogress, argmemonly and nosync should imply willreturn. However, FuncAttrs currently infers neither nosync nor argmemonly, so it would need those first. I think that the argmemonly check here was there to cover some common intrinsics like llvm.memcpy, but those are explicitly willreturn now. |
llvm/lib/Analysis/ValueTracking.cpp | ||
---|---|---|
5046 | Drive by comment: if this reads volatile memory, it is not side-effect free? If this is a check for "side-effect free intrinsics", does this check cover that? |
llvm/lib/Analysis/ValueTracking.cpp | ||
---|---|---|
5046 | Unfortunately this is not completely clear from the readonly definition, but I don't think to would currently be safe to treat functions with volatile or atomic loads as readonly. They are currently treated as may-write-to-memory, see https://llvm.org/docs/LangRef.html#volatile-memory-accesses We have nosync to model some of those aspects separately, but it is not really used at the moment. |
llvm/lib/Analysis/ValueTracking.cpp | ||
---|---|---|
5046 |
Yes, that's what I think (also from reading langref). @samparker remarked that we could perhaps also check the IntrHasSideEffects intrinsic property? |
llvm/lib/Analysis/ValueTracking.cpp | ||
---|---|---|
5046 |
I think that's only accessible in the backend at the moment? |
llvm/lib/Analysis/ValueTracking.cpp | ||
---|---|---|
5046 |
And, IMHO, it is conceptually broken to have such "hidden side effects" in the first place. If you don't model you behavior in the IR properly how is any of this supposed to work. We might need more "side effect categories" but that is a different conversation. |
Yeah, I agree that mustprogress, argmemonly and nosync should imply willreturn. However, FuncAttrs currently infers neither nosync nor argmemonly, so it would need those first. I think that the argmemonly check here was there to cover some common intrinsics like llvm.memcpy, but those are explicitly willreturn now.
Post release branch we should start running a light Attributor, to get things like nosync, argmemonly, ... one by one.
But just for my understanding, does this mean there’s a problem that we intend to fix after the release?
I don't think there's a problem per-se. There will be a few cases where we now fail to remove dead calls, because willreturn is not being inferred, even though the function is actually willreturn. So far, we do not have any indication that this is causing performance problems in practice, but we should keep a close eye on the impact. (And there are still places in tree that assume functions will return, without willreturn, which potentially still hides some of the negative impact).
Going forward, we now have greater motivation to improve attribute inference, because there's a tangible benefit, where none was before ('as long as willreturn is not useful, why infer it?'). I think what Johannes is eluding to is that now there is a bigger motivation to move towards using parts of the attributor to improve the inference.
Drive by comment: if this reads volatile memory, it is not side-effect free? If this is a check for "side-effect free intrinsics", does this check cover that?