Quantcast
Channel: Active questions tagged gcc - Stack Overflow
Viewing all articles
Browse latest Browse all 22058

Does the inline asm compiler barrier (memory clobber) count as an external function, or as static function call?

$
0
0

Introduction/confirmation of basic facts

It is well known that with GCC style C and C++ compilers, you can use inline assembly with a "memory" clobber:

asm("":::"memory");

to prevent reordering of (most) code past it, acting as a (thread local) "memory barrier" (for example for the purpose of interacting with async signals).

Note: these "compiler barriers" do NOT accomplish inter-threads synchronization.

It does the equivalent of a call to a non inline function, potentially reading all objects that can be read outside of the current scope and altering all those that can be altered (non const objects):

int i;

void f() {
   int j = i;
   asm("":::"memory"); // can change i
   j += i; // not j *= 2
   // ... (assume j isn't unused)
}

Essentially it's the same as calling a NOP function that's separately compiled, except that the non inline NOP function call is later (1) inlined so nothing survives from it.

(1) say, after compiler middle pass, after analysis

So here j cannot be changed as it's local, and is still the copy of the old i value, but i might have changed, so the compilation is pretty much the same as:

volatile int vi;

int f2() {
   int j = vi;
   ; // can "change" vi
   j += vi; // not j *= 2
   return j;
}

Both reads of vi are needed (for a different reason) so the compiler doesn't change that into 2*vi.

Is my understanding correct up to that point? (I presume it is. Otherwise the question doesn't make sense.)

The real issue: extern or static

The above was just the preamble. The issue I have is with static variables, possible calls to static functions (or the C++ equivalent, anonymous namespaces):

Can a memory clobber access static data that isn't otherwise accessible via non static functions, and call static functions that aren't otherwise callable, as none of these are visible at link stage, from other modules, if they aren't named explicitly in the input arguments of the asm directive?

static int si;

int f3() {
   int j = si;
   asm("":::"memory"); // can access si?
   j += si; // optimized to j = si*2; ?
   return j;
}

In other words, is that "clobber" the equivalent of a call to:

  • an external NOP function, which wouldn't be able to name si directly, nor to access it in any indirect way, as no function in the TU either communicates the address of si, or makes si indirectly modifiable
  • a locally defined NOP function that can access si

?

Bonus question: global optimization

If the answer is that static variables aren't treated like extern variables in that case, what is the impact when compiling the program at once? More specifically:

During global compilation of the whole program, with global analysis and inference over variables values, is the knowledge of the fact that for example a global variable is never modified (or never assigned a negative value...), except possibly in an asm"clobber", an input of the optimizer?

In other words, if non static i is only named in one TU, can it be optimized as if it was a static int even if there are asm statements? Should global variables be explicitly listed as clobbers in that case?


Viewing all articles
Browse latest Browse all 22058

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>