Is volatile initialization of a fundamental type observable behavior?

Consider this function:

void f(void* loc) { auto p = new(loc) volatile int{42}; *p = 0; } 

I checked the generated code with clang, gcc and CL, none of which went beyond initialization. (The answer can be reviewed by the device :).

Is this an extension provided by compilers to the standard? Does the standard allow compilers not to write 42?

Actualy for objects of type class, it is indicated that the constructor of the object is ignored for the volatile classifier [class.ctor]:

The constructor can be called on a const, volatile or const volatile object. const and unstable semantics (10.1.7.1) do not apply to the construction of an object. They take effect when the constructor for the most derived object (4.5).

+7
c ++ initialization language-lawyer volatile
source share
2 answers

[intro.execution] / 8 lists the minimum requirements for the corresponding implementation; they are also known as "observed behavior." The first requirement is that "access to unstable objects is evaluated strictly in accordance with the rules of an abstract machine." The compiler must produce all observable behavior. In particular, it is not permitted to remove calls to unstable objects. And note that here the “object” is used in the sense of a compiler-writer: it includes built-in types.

0
source share

This is not a consistent question, because what it means is that the compiler is writing depends on the platform. There is no platform-independent view of writing, other than perhaps observing the effects of writing in subsequent reading.

As you can see, typical x86 compilers will give a write instruction, but without a memory barrier. The processor can change the write order, compile it, or even avoid writing to main memory due to how the coherence of the platform cache works.

The reason they made this choice is because it makes volatile work for a wide range of applications, including those where the standard requires it to work, and because it has acceptable performance implications. The standard, being neutral with respect to the platform, does not dictate solutions specific to the platform like this, and the authors of the compiler do not understand this in order to do this.

They could cause each volatile access to be uncoalsecable, un-reorderable and push through the cache subsystem into main memory. But this would provide terrible performance, and there would be no significant advantages on this platform. Therefore, they don’t do this, and they don’t understand the C ++ standard to suggest that there is some mythical observer on the memory bus that needs to see specific things. The very existence of a memory bus is platform specific. The standard is platform independent.

Sometimes it seems to you that people, for example, say that the standard somehow requires the compiler to issue instructions for writing volatile in order, but it doesn’t matter if the CPU merges or overwrites the records. This is, frankly, stupid. The C ++ standard does not impose requirements on team compilers, but rather on what these instructions must follow when executed. It does not distinguish between optimizations performed by the processor and optimizations performed by the compiler, and any such differences will in any case be related to the platform.

If the standard allows the processor to reorder two records, it allows the compiler to reorder them. He does not do this and cannot make such a difference. Of course, compiler developers can still decide that they will write records, even if the CPU can reorder them, because it can make the most sense on their platform.

0
source share

All Articles