avr-libc-dev
[Top][All Lists]
Advanced

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

[avr-libc-dev] User-manual/optimization.html


From: David Brown
Subject: [avr-libc-dev] User-manual/optimization.html
Date: Thu, 18 Jun 2015 14:58:00 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.2.0

Hi,

In the user manual:

<http://www.nongnu.org/avr-libc/user-manual/optimization.html>

there is a discussion about the unexpected code generation from:

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


This came up recently in a gcc-help mailing list question - the problem
is that the call to __udivmodhi4 may be generated after the cli
instruction, disabling interrupts for longer than necessary.  The web
page says there is no way to force the desired code generation (with
"val" being calculated before "cli").

However, there /is/ a way to get the right results - using a fake
assembly input to force the calculation:

#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 memory clobber on cli() and sei() ensures that no memory operations
are moved before or after those statements.  But as already noted, the
memory clobber does not affect non-memory operations such as
calculations or register-only manipulation.

But the extra "asm volatile" here with a fake input tells the compiler
that "val" is an input to the (empty) assembly, and must therefore be
calculated before the statement is executed.  The empty input constraint
(no "r" or "m") gives the compiler complete freedom about where it wants
to put this fake input - all we are saying is that the value "val" must
be calculated before executing

    asm volatile("" :: "" (val))

Generating assembly from this (using gcc-4.5.1, which is the latest
avr-gcc I have installed at the moment) shows the division being done
before the cli() - the code is optimal and correct, with no unnecessary
memory operations (as you would need by making "val" volatile).



Could the documentation and web page be updated to include this
solution, for the benefit of others who find it (not just avr-libc users)?


-- 
Vennlig hilsen / Best regards

*David Brown*
Westcontrol AS
Systemutvikler / Systems Developer

Tlf.:   +47 5174 1031
Mob.:   +47 977 37 328
E-mail: address@hidden
Web:    http://www.westcontrol.com




reply via email to

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