Re: asm volatile statement reordering

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

 



On 17/10/17 09:58, Andrew Haley wrote:
> On 17/10/17 08:32, Jeffrey Walton wrote:
>> GCC guesses wrong on occasion. It will remove code that has value that
>> but does not produce an output because the language does not allow us
>> to express it.
>>
>> The C language lacks what we need to express what we need to do. Its a
>> failure of the C (and C++) committees. Its not a GCC failure.

gcc is a tool that goes above and beyond C and C++.  It is not /just/ a
C and C++ compiler.  After all, the language standards don't have "asm"
at all.

It is important to remember that gcc is used for many types of
programming - in particular, it is the most used tool for embedded
programming.  And the point of gcc is to be a useful tool for its users.
 So if users have trouble getting the ordering they need from gcc, then
it /is/ a gcc failure.  Sure, it would be nice if the C and C++
languages gave the features needed (and C11 and C++11 atomics and fences
go some way towards that), but it is up to gcc to handle things that are
clearly implementation-dependent behaviour, and compiler extensions.
And users use /gcc/ - they don't use a standards document.

As gcc gets smarter with its optimisations, and doing more code
re-organisation, I see more and more problems in embedded code.  We need
guarantees about code order - either rules that we /know/ gcc will
follow, or additional features to fill the gaps.  gcc developers can't
just tell embedded users "You see that code you had that worked fine
with gcc 3 to gcc 7?  Well, it won't work now with gcc 8.  You should
have studied ISO 9899:201x section 5.1.2.3p6 better".

Don't get me wrong here - I am not trying to demand features from gcc.
Nor am I suggesting that users (embedded developers or otherwise) should
not learn the details of the C language, or that they should not have to
read the gcc documentation.

I am trying to establish exactly what gcc does, and what guarantees it
may or may not give.  Based on that, I can see if current solutions in
source code are strong enough, or if they need workarounds, and if I
should be filing an enhancement request.

> 
> I disagree.  If you want a bunch of asms to execute in a particular
> order, add a memory clobber or some dependencies.  It's not difficult
> once you have the understanding.  In this particular case, fixing it
> is trivial, and there are many ways to do it.
> 

I understand about dependencies.  (I also know about memory clobbers,
but these tend to be a fairly blunt instrument and can lead to wasted
cpu cycles, especially on RISC cpus with lots of registers.  When you
are dealing with things like critical sections with interrupts disabled,
you are often trying to minimise the cycle time.)  My solution to this
particular ordering problem is:

    uint32_t status;
    asm volatile ("mrs %0, PRIMASK" : "=r" (status) :: );
    asm volatile ("cpsid i" :: "" (status) :);

    foo();

    asm volatile ("msr PRIMASK, %0" :: "r" (status) : );


The dependency on "status" in the "cpsid i" assembly line ensures that
it must be ordered after the "save PRIMASK" line.  However, I know of no
clear way - other than a potentially costly memory clobber - of forcing
the ordering of the "cpsid i" assembly before foo(), and the "restore
PRIMASK" line after foo().

But all my testing suggests that asm volatile statements with no outputs
are not moved past each other, or past other observable behaviour
(volatile memory accesses, external functions that might have such
accesses, etc.).

If that suggestion is true, then the solution above is not only a
correct fix, but it also results in optimal code - while a memory
clobber is definitely sub-optimal.







[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux