[llvm-dev] [isocpp-parallel] Proposal for new memory_order_consume definition

Michael Matz via llvm-dev llvm-dev at lists.llvm.org
Mon Feb 29 10:17:55 PST 2016


Hi,

On Sat, 27 Feb 2016, Paul E. McKenney wrote:

> But we do already have something very similar with signed integer
> overflow.  If the compiler can see a way to generate faster code that
> does not handle the overflow case, then the semantics suddenly change
> from twos-complement arithmetic to something very strange.  The standard
> does not specify all the ways that the implementation might deduce that
> faster code can be generated by ignoring the overflow case, it instead
> simply says that signed integer overflow invoked undefined behavior.
> 
> And if that is a problem, you use unsigned integers instead of signed
> integers.
> 
> So it seems that we should be able to do something very similar here.

For this case the important pice of information to convey one or the other 
meaning in source code is the _type_ of involved entities, not annotations 
on the operations.  signed type -> undefined overflow, unsigned type -> 
modulo arithmetic; easy, and it nicely carries automatically through 
operation chains (and pointers) without any annotations.

I feel much of the complexity in the memory order specifications, also 
with your recent (much better) wording to explain dependency chains, would 
be much easier if the 'carries-dependency' would be encoded into the types 
of operands.  For purpose of example, let's call the marker "blaeh" (not 
atomic to not confuse with existing use :) ):

int foo;
blaeh int global;
int *somep;
blae int *blaehp;
f () {
  blaehp = &foo;  // might be okay, adds restrictions on accesses through 
                  // blaehp, but not through 'foo' directly
  blaehp = &global;
  if (somep == blaehp)
    {
      /* Even though the value is equal ... */
      ... *blaehp ... /* ... a compiler can't rewrite this into *somep */
    }
}

A "carries-dependency" on some operation (e.g. a call) would be added by 
using a properly typed pointer at those arguments (or return type) where 
it matters.  You can't give a blaeh pointer to something only accepting 
non-blaeh pointers (without cast).

Pointer addition and similar transformations involving a blaeh pointer and 
some integer would still give a blaeh pointer, and hence by default also 
solve the problem of cancellations.

Such marking via types would not solve all problems in an optimal way if 
you had two overlapping but independend dependency chains (all of them 
would collapse to one chain and hence made dependend, which still is 
conservatively correct).

OTOH introducing new type qualifiers is a much larger undertaking, so I 
can understand one wants to avoid this.  I think it'd ultimately be 
clearer, though.


Ciao,
Michael.


More information about the llvm-dev mailing list