[PATCH] D101701: [nofree] Refine concurrency requirements

Nicolai Hähnle via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue May 11 15:53:53 PDT 2021


nhaehnle added a comment.

In D101701#2750507 <https://reviews.llvm.org/D101701#2750507>, @nhaehnle wrote:

> In D101701#2747864 <https://reviews.llvm.org/D101701#2747864>, @jdoerfert wrote:
>
>> `nofree` functions imply `nofree` arguments so it very much makes a difference if we make it harder to infer
>> and annotate the former. As we already moved to a more semantic-based definition of escaped we can actually
>> look at an example where this makes a difference. Take pointers passed via memory to see how you cannot just
>>  move the `nofree` to account for the change made by this patch:
>>
>>   struct { int *a } s;
>>   s.a = malloc()               // this is a store.
>>   nofree_nocapture_only(&s)    // we can potentially show `s.a` is not captured in the function but we cannot
>>                                // annotate that fact as a `nofree` argument without argument promotion, which
>>                                // we cannot always do.
>>   // s.a is still known to be dereferenceable even without `nosync`. The function `nofree` is needed, `nofree`
>>   // argument attributes are not involved.
>
> Is that actually true? Regardless of the nocapture flag, s.a may be passed to another thread which then frees it. (nocapture only applies to &s in the first place, and even then, it does not say anything about **temporary** copies of the pointer that may be passed to other threads.)

I realize now that I was partially wrong about this: the definition of the `nocapture` attribute does say that the function cannot send the pointer to another thread, but the pointer in question is &s. So it still seems to me that in the example, the callee is allowed to send s.a to another thread which then frees it (given today's definition of `nofree`).

If this example does fall like I think it does, is there still an optimization benefit to having the **function attribute** `nofree` as defined today vs. as defined in this patch? As I see it, there were three arguments:

1. Inference doesn't have to worry about synchronization.
2. Other attributes work the same way; however, this is false at least for `argmemonly` and arguably also for `inaccessiblememonly`, except that one presumably never gets inferred?
3. Today's `nofree` enables annotations and optimizations that the proposed change would no longer allow. I can't say for certain whether this is false, but at least the examples given so far seem to fail (the first one because you can just use the `nofree` **argument attribute** instead, and the second is discussed above in this comment).

That leaves as a single argument the complexity of inference, but how strong of an argument is that, really?

P.S.: The example I have in mind where confusion about `argmemonly` can be used to trigger a miscompile is at https://godbolt.org/z/dEG8n6W3E. Current main merges the two loads from %q, which is incorrect since `@setup` could arrange for a second thread to be created which changes its value in between.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D101701/new/

https://reviews.llvm.org/D101701



More information about the llvm-commits mailing list