RE: Control Dependencies vs C Compilers

From: David Laight
Date: Tue Oct 06 2020 - 08:37:13 EST


From: Peter Zijlstra
> Sent: 06 October 2020 12:47
> Hi,
>
> Let's give this linux-toolchains thing a test-run...
>
> As some of you might know, there's a bit of a discrepancy between what
> compiler and kernel people consider 'valid' use of the compiler :-)
>
> One area where this shows up is in implicit (memory) ordering provided
> by the hardware, which we kernel people would like to use to avoid
> explicit fences (expensive) but which the compiler is unaware of and
> could ruin (bad).
...
>
> In short, the control dependency relies on the hardware never
> speculating stores (instant OOTA) to provide a LOAD->STORE ordering.
> That is, a LOAD must be completed to resolve a conditional branch, the
> STORE is after the branch and cannot be made visible until the branch is
> determined (which implies the load is complete).
>
> However, our 'dear' C language has no clue of any of this.
>
> So given code like:
>
> x = *foo;
> if (x > 42)
> *bar = 1;
>
> Which, if literally translated into assembly, would provide a
> LOAD->STORE order between foo and bar, could, in the hands of an
> evil^Woptimizing compiler, become:
>
> x = *foo;
> *bar = 1;
>
> because it knows, through value tracking, that the condition must be
> true.
>
> Our Documentation/memory-barriers.txt has a Control Dependencies section
> (which I shall not replicate here for brevity) which lists a number of
> caveats. But in general the work-around we use is:
>
> x = READ_ONCE(*foo);
> if (x > 42)
> WRITE_ONCE(*bar, 1);

An alternative is to 'persuade' the compiler that
any 'tracked' value for a local variable is invalid.
Rather like the way that barrier() 'invalidates' memory.
So you generate:

x = *foo
asm ("" : "+r" (x));
if (x > 42)
*bar = 1;

Since the "+r" constraint indicates that the value of 'x'
might have changed it can't optimise based on any
presumed old value.
(Unless it looks inside the asm opcodes...)

David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)