avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-gcc-list] Avr-libc-user-manual: "Problems with reordering code"


From: David Brown
Subject: Re: [avr-gcc-list] Avr-libc-user-manual: "Problems with reordering code"
Date: Thu, 8 Dec 2016 13:10:29 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.2.0

On 07/12/16 00:42, Marcin Godlewski wrote:
> Dear all,
>  
> I'm writing with reference to the following paragraph in avr libc manual:
> http://www.nongnu.org/avr-libc/user-manual/optimization.html#optim_code_reorder
>  
> It is stated there: "However, memory barrier works well in ensuring that
> all volatile accesses before and after the barrier occur in the given
> order with respect to the barrier. However, it does not ensure the
> compiler moving non-volatile-related statements across the barrier.
> Peter Dannegger provided a nice example of this effect:(...)". The text
> is followed by an example.

There /is/ a good (IMHO) solution to this without using unnecessary
memory stores:

#define cli() __asm volatile( "cli" ::: "memory" )
#define sei() __asm volatile( "sei" ::: "memory" )
unsigned int ivar;
void test2( unsigned int val )
{
    val = 65535U / val;
    asm volatile("" :: "" (val));
    cli();
    ivar = val;
    sei();
}

The assembly here tells the compiler that we are going to use "val", so
it must be available before "executing" the assembly line.  But since
the assembly line does nothing, no extra work is involved - nothing is
stored or loaded unnecessarily.

For my own use, I have it in a macro.  There is also a macro here that
tells the compiler to "forget" what it knows about a variable - the
compiler needs to know it's state before the assembly (since the
asssembly "uses" it), and it needs to assume that the assembly might
change it.  But again, no unnecessary code is generated, and the
variables can happily remain in registers all the time.


// Ensure that "val" has been calculated before next volatile access
// by requiring it as an assembly input.  Note that only volatiles are
ordered!
#define forceDependency(val) \
                asm volatile("" :: "" (val) : )

// Tell the compiler that it no longer knows about "v", without actually
changing it.
// This can be used to break relationships or ranges that the compiler
knows due
// to array information, type-based analysis, etc.
#define forgetCompilerKnowledge(v) \
                asm volatile ("" : "+g" (v))


>  
> My understanding of the example is that what _probably_ made the
> operation being moved accross the barrier is that it involved only local
> data. This example doesn't show that any operations on global data can
> be moved accross the barrier. I think that the conclusion that a barrier
> prevents only operations on volatile data from being reordered accross
> the barrier is wrong. No operation on global data should be reordered
> accross the barrier, even on non-volatile data. But apparently,
> operations on local data can, which by the way makes some sense.
>  
> The definition of a barrier ensuring that "all volatile accesses before
> and after the barrier occur in the given order with respect to the
> barrier" doesn't make much sense as this is already guaranteed by the C
> language standard. Per standard, any operations on volatile variables
> must be evaluated according to the rules of the abstract machine.
>  
> Please let me know what is your view on the subject.
>  
> Best regards,Marcin Godlewski
>  
>  
> 
> 
> _______________________________________________
> AVR-GCC-list mailing list
> address@hidden
> https://lists.nongnu.org/mailman/listinfo/avr-gcc-list
> 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]