Are arrays guaranteed to be affected by a "memory" clobber?

Andrew Haley aph@redhat.com
Sat Jun 13 19:51:00 GMT 2015


On 13/06/15 18:49, Sebastian wrote:
> On Fri, 12 Jun 2015 19:53:03 +0100
> Andrew Haley <aph@redhat.com> wrote:
> 
>>> That's the whole point about the example.
>>
>> No it's not.  The only thing moved across the barrier is the
>> division.  A memory op cannot  be moved across a memory barrier.

> One memory barrier is at the cli(), as the article points out "where
> the potentially slow division is moved across cli(),". The
> assignment to val is moved, over that.

Ah, okay.  I wasn't even thinking of that assignment as a memory
operation: see below.

> It was before cli() in the C
> source and it's after cli() after optimization. As your own comment
> shows.
> 
>> Here's the code:
>>
>> 00000112 <test2>:
>>  112:   bc 01           movw    r22, r24
>>  114:   f8 94           cli
> That's the cli().
> 
>>  116:   8f ef           ldi     r24, 0xFF       ; 255
>>  118:   9f ef           ldi     r25, 0xFF       ; 255
>>  11a:   0e 94 96 00     call    0x12c   ; 0x12c <__udivmodhi4>
>>  11e:   70 93 01 02     sts     0x0201, r23
>>  122:   60 93 00 02     sts     0x0200, r22
>>
>> The store to val is here ^

> Thanks. Didn't try to find that, just figured that it would be
> difficult to assign the result of the division before the division
> happened.

> So you just confirmed everything. This is after cli().

> Actually, I think you're wrong here - this is not the store to val
> (I guess you could r24 consider to be val, since that's it at the
> beginning of the function), it's the store to ivar.

Sorry, yes.  I made a mistake.  I meant the store to ivar.

> The store to val never happens, it is optimized away because val is
> not a volatile variable, it's just a temporary one which is never
> used afterwards.

Yes.  val has been eliminated by the compiler.

> Which, still, is the point of the article: Because val is not
> declared volatile, it is not "memory", so assignments to it (and the
> division required to happen before the assignment) can be moved
> across the barrier.

The question of whether a local variable is considered by GCC to be
"in memory" depends on whether it has ever had its address taken.

So, if you say

   int n;
   int *p = &n;

then n is potentially a memory operand.  (But be careful not to extend
this too far: if GCC knows that p is not used, it may be eliminated
and n is no longer potentially in memory.)  If a variable is global it
is also a memory operand.  But if a local variable never has its
address taken, no memory operation can access it (because there is no
way to know where it is.)  Therefore it is not affected by a memory
clobber.

> So, again, why would it be ok to remove the volatile qualifier from
> my array elements?  How else can I be sure a variable of mine is
> "memory"?

The only way to be really sure is to use volatile.  But it depends
on exactly what you're trying to do: if you're more specific we can
provide better advice.

Andrew.



More information about the Gcc-help mailing list