Ralf Jung via llvm-dev
2017-Dec-23 13:42 UTC
[llvm-dev] Hoisting in the presence of volatile loads.
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? *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 via llvm-dev
2017-Dec-23 14:39 UTC
[llvm-dev] Hoisting in the presence of volatile loads.
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
George Burgess IV via llvm-dev
2017-Dec-23 17:50 UTC
[llvm-dev] Hoisting in the presence of volatile loads.
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 >