[llvm-dev] Hoisting in the presence of volatile loads.

George Burgess IV via llvm-dev llvm-dev at lists.llvm.org
Sat Dec 23 09:50:24 PST 2017


Right. This conversation was primarily about loads, not stores.

On Sat, Dec 23, 2017 at 6:39 AM, Hal Finkel <hfinkel at anl.gov> wrote:
>
> On 12/23/2017 07:42 AM, Ralf Jung wrote:
>>
>> Hi all,
>>
>>>> I think that this is the right way to approach this: we should change
>>>> MemorySSA to be less conservative in this regard. LLVM's language
>>>> reference is
>>>> pretty explicit about reordering volatile and non-volatile operations:
>>>>
>>>>> The optimizers must not change the number of volatile operations or
>>>>> change
>>>>> their order of execution relative to other volatile operations. The
>>>>> optimizers /may/ change the order of volatile operations relative to
>>>>> non-volatile operations. This is not Java’s “volatile” and has no
>>>>> cross-thread synchronization behavior.
>>>>
>>>> I see no reason to prevent this kind of reordering, even if the volatile
>>>> and
>>>> non-volatile accesses might alias.
>>>
>>> Just to chime in here since I was explicitly CCd, I agree with this
>>> conclusion
>>> and believe this thread reached the proper result per the appropriate
>>> specs.
>>
>> Please forgive my possible naive question, but I do not understand how
>> "accessing a volatile object through a non-volatile pointer is UB" is
>> enough to
>> justify this optimization.  Don't you also need "accessing a non-volatile
>> object
>> through a volatile pointer is UB"?
>>
>> In other words, if I understand correctly, this proposed reordering could
>> change
>> the behavior of the following program:  <https://godbolt.org/g/zH1Tey>
>>
>>
>> static void foo(int *x, volatile int *y) {
>>      // These may be reordered now?
>
>
> No. Unless we can somehow prove that x and y don't alias, then the ordering
> must be preserved (because, if they do alias, then the final result must be
> 5). volatile should have nothing to do with that.
>
>  -Hal
>
>>      *x = 4;
>>      *y = 5;
>> }
>>
>> int bar() {
>>      int x = 0;
>>      foo(&x, (volatile int*)&x);
>>      return x; // MUST return 5
>> }
>>
>>
>> `x` and `y` alias in `foo` and both point to a non-volatile object;
>> reordering
>> them changes what `bar` returns.  Notice that casts to volatile pointers
>> are
>> pretty common e.g. in the Linux kernel:
>>
>>    #define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
>>
>> Am I missing something?
>>
>> Kind regards,
>> Ralf
>
>
> --
> Hal Finkel
> Lead, Compiler Technology and Programming Languages
> Leadership Computing Facility
> Argonne National Laboratory
>


More information about the llvm-dev mailing list