C++ Logo

std-discussion

Advanced search

Re: pointer to volatile, but no volatile object

From: Federico Kircheis <federico_at_[hidden]>
Date: Mon, 5 Jun 2023 21:42:12 +0200
On 05/06/2023 21.05, Tom Honermann wrote:
> On 6/5/23 1:43 PM, Federico Kircheis via Std-Discussion wrote:
>> Hello, I have a question about following snippet of code
>>
>> ----
>> void bar(volatile int& b){
>> b=42;
>> }
>>
>> void foo()
>> {
>> int a = -1;
>> bar(a);
>> }
>> ----
>>
>> With GCC, clang and MSVC, and optimization enabled, a is set to 42,
>> even if a is not a volatile object, and bar completely inlined inside
>> foo:
>>
>> ----
>> bar(int volatile&):
>> mov DWORD PTR [rdi], 42
>> ret
>> foo():
>> mov DWORD PTR [rsp-4], 42
>> ret
>> ----
>>
>> This surprised me, because as far as I know, the standard mostly talks
>> about glvalues
>>
>> > Accesses through volatile glvalues are evaluated strictly according
>> to the rules of the abstract machine.
>>
>> > Reading an object designated by a volatile glvalue (7.2.1),
>> modifying an object, calling a library I/O function, or calling a
>> function that does any of those operations are all side effects, which
>> are changes in the state of the execution environment.
>>
>> and not about pointers marked as volatile to objects that are not.
>> Thus my understanding was that since a is not volatile, compilers are
>> allowed to optimize the "mov DWORD PTR [rsp-4], 42" away.
>
> In bar(), the expression b yields a glvalue to an object of volatile
> type and inlining doesn't change that.


Oops, my original example was

----
void bar(volatile int* b){
      *b=42;
}
void foo()
{
      int a = -1;
      bar(&a);
}
----
then tried with a reference and pasted that.
But nothing in your explanation changes, thanks ;)
> That being said, since a is a local variable that an implementation can 
> infer is not associated with memory for which reads or writes have side 
> effects (other than to change the value of the variable) and since it is 
> provable that there are no other volatile access expressions that impose 
> an ordering relationship, I think implementations could elide the write. 
> That they don't might be a missed optimization (perhaps because, in 
> general, it might be difficult to prove that the write can be elided or 
> because there is so little to gain from such elision).
> 
> Tom.
>> Is my interpretation incorrect and are those optimizations not 
>> allowed, or are compilers less aggressive when there are volatile 
>> pointers, as some code bases/users might "hide" non-volatile objects 
>> behind pointers to volatile objects to try to avoid some optimization?
>>
>> (removing volatile from the function signature as bar optimizes foo as 
>> expected)
>>
>> Best
>>
>> Federico
For what is worth, even a static_cast seems to hinder optimizations
void foo(){
     int a = -1;
     *static_cast<volatile int*>(&a) = 42;
}

Received on 2023-06-05 19:42:17