1

I've been continuously trying to wrap my head around this ordering model and how it's useful. This answer states

no loads that are dependent on the newly loaded value can be reordered wrt. the atomic load. I.e. if they are after the atomic load in the source code, they will happen after the atomic load too.

However, this makes no sense to me since it would be impossible to perform the later loads without value being read in by the first atomic load. This post provides a good overview of the consistency models, and it states that the ARM and Power architectures have a weak ordering model, except they enforce data-dependency ordering.

Does this mean that consume_memory_order is useless in every major architecture except Alpha?

If not, then given the example below, what and where can the instructions be reordered?

ldr r1, [r0]
ldr r7, [r0]
str r2, [r0]
ldr r3, [r1]
str r7, [r3]
ldr r4, [r3]
squirem
  • 227
  • 1
  • 11
  • 1
    memory_order_consume is borked in definition and unimplemented by most compilers (is mapped to acquire). The original reason for this memory order were platforms with data dependendency ordering where acquire would mean full memory barrier. (so it has nothing to do with Alpha and everything with ARM) – rAndom69 May 29 '17 at 07:22
  • @rAndom69 Why bother mapping it to acquire ordering instead of just relaxed ordered if the architecture guarantees data-dependency ordering anyway? – squirem May 29 '17 at 08:25
  • 1
    I assume this is due to implementation complexity. acquire is valid replacement for consume within c++11 memory model (although "heavy" on some platforms). data dependency ordering on processor level also requires injecting dependencies into assembly + relaxed operations do not impose order (they may be reordered wrt each other). consider syntax like: int z = x.load(consume); a = v[z-z]; this carries dependency from x into load from v, however z-z will be optimized away by compiler and thus v load could be reordered before relaxed x load by cpu OoOE. – rAndom69 May 29 '17 at 09:08
  • 1
    While AFAIK all processors except ALPHA obey dependency ordering automatically, the problem is that *the C++ language doesn't*. If you write code that assumes dependency ordering without telling he compiler about it, you are causing undefined behavior. – EOF May 29 '17 at 16:17
  • @EOF I'm a bit confused by this. How can the compiler produce code where dependency ordering isn't enforced if the hardware is enforcing dependency ordering itself? When you say "undefined behavior", do you mean from the C++ standard' point-of-view, or do mean the program will actually produce unexpected results. – squirem May 29 '17 at 16:37
  • 1
    @squirem: The typical example would be something like `int a = load(); b = ptr[a-a];`. While weakly-ordered architectures like ARM or POWER will keep dependencies through operations like `a^a` or `a-a` or `a&0` (unlike x86, which will break dependency chains on some of those), the *compiler* can remove them if the `load()` is not at least `memory_order_consume` (Actually compilers *have* removed this kind of dependency in spite of `memory_order_consume`, which is why it is considered broken by deign). – EOF May 29 '17 at 17:16
  • @rAndom69 Okay, I finally get it. There are cases where the load/store index can be determined at compile-time without needing to perform a calculation with the variables involved. You post your comment as an answer. – squirem May 29 '17 at 17:56

0 Answers0