This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: basic asm and memory clobbers


On 11/16/2015 10:55 PM, David Wohlferd wrote:

- There is no standard that says it must do this.
True. But these after all are extensions and extensions have been notoriously under-documented through the years.

- I'm only aware of 1 person who has ever asked for this change. And the
request has been deemed so unimportant it has languished for a very long
time.
True. But I'd say for this case it means it just hasn't been high enough on anyone's priority list to get resolved. I wouldn't be at all surprised if Richard filed this bug to ensure that it didn't get lost. That's standard development procedure for items we notice, but aren't actively working on.

It's unfortunate that Andrew muddied the waters. Andrew's conclusions, particularly in c#6 are simply wrong.


- There is a plausible work-around with extended asm, which (mostly) has
clear semantics regarding clobbers.
Converting an old-style asm to extended asm can be painful. ANd in the case of legacy code the conversion process itself is a potential source of bugs.




- While the change probably won't introduce bad code, if it does it will
be in ways that are going to be difficult to track down, in an area
where few have the expertise to debug.
- Existing code that currently does things 'right' (ie push/pop any
modified registers) will suddenly be doing things 'wrong,' or at least
wastefully.
- Other than top-level asm, it seems like every existing basic asm will
(probably) get a new performance penalty (memory usage + code size +
cycles) to allow for situations they may already be handling correctly
or that don't apply.
True, these aren't particularly compelling reasons to not make the
change.  But I also don't see any compelling benefits to offset them.
The benefit is traditional asms do the expected thing. With no way to describe dataflow, the only rational behaviour for a traditional asm is that it has to be considered a use/clobber of memory and hard registers.

The fact that it wasn't documented that way eons ago is simply a documentation bug -- likely due to the fact that back when the documentation for traditional asms was written, there were virtually no optimizations of memory referencing instructions -- essentially folks didn't ponder (much less document) how these asms would interact with memory.

In fact, if you go back to the change I made back in 1999 referenced by this BZ, you'll find that we had a mis-compilation of code around an ASM by a pass to remove redundant stores that had just been significantly improved.




For existing users, presumably they have already found whatever solution
they need and will just be annoyed that they have to revisit their code
to see the impact of this change.  Will they need to #if to ensure
consistent performance/function between gcc versions?  For future users,
they will have the docs telling them the behavior, and pointing them to
the (now well documented) extended asm.  Where's the benefit?
Existing users have to change nothing when we fix 24414. The whole point behind 24414 is to point out a case where we are not honoring the uses/clobbers all hard regs and memory semantics of traditional asms.



But changing this so gcc tries (probably futilely) to emulate other
implementations of asm...  That seems like a weak case to support a
change to this long-time behavior.  Unless there are other benefits I'm
just not seeing?
When we fix 24414 by honoring the "uses/clobbers all hard registers and memory" semantics for old-style asms, those old-style asms will be *less* likely to cause problems in the presence of ever-improving optimization techniques.



--------------
Ok, that's my best shot.  You have way more expertise and experience
here than I do, so I expect that after you think it over, you'll make
the right call.  And despite my attempt here to defend the opposite
side, I'm not entirely sure what the right call is.  But these seem like
the right questions.

Either way, let me know if I can help.
About the only immediate task would be to ensure that the documentation for traditional asms clearly documents the desired semantics and somehow note that there are known bugs in the implementation (ie 24414, handling of flags registers, and probably other oddities)

Whether that means clobbering memory or not, I don't much care -- with
the status quo, if you want your asm to clobber memory you have to use
extended asm; if basic asm is made to clobber memory, if you want your
asm to *not* clobber memory you have to use extended asm (which you
can with no operands by writing e.g.  asm("bork" : );  ).  So both
behaviours are available whether we make a change or not.

But changing things now will likely break user code.
Having an traditional asm clobber memory should not break user code.
It may pessimize it slightly, but if it does, that code was already
broken.

How much pessimism are we talking here?  Wouldn't clobbering everything
effectively force the reloading of (some? most? all?) registers?  And
more memory will be needed to store things that used to just require
registers?  Along with a few more memory writes?  A single line of basic
asm, even a comment, could have a non-trivial impact on the code that
gets generated.
Essentially it means that old style asms become a point where the compiler has to assume that memory and hard registers are read/clobbered. Without going into all the details the asm essentially invalidates information the compiler might be tracking about the value in memory locations or hard registers.

So given two stores to the same memory location on opposite sides of the traditional asm, the compiler is _not_ allowed to remove the first store (because the traditional asm might read the value). Nor is the compiler allowed to remove the second store (because the asm might have stored a value into that location).

Similar situations occur when reading memory locations.


One common use I've seen for basic asm is "int $3" on x86 to break into
the debugger (the basic asm docs use this as a sample). Changing this to
a clobber-everything will make what used to be a minimally intrusive way
to debug code into a high impact operation that may obscure the very
thing being debugged.
Actually in that specific case, ensuring everything is consistent is actually a *good* thing. And I suspect it's still a lot less intrusive than you might think.

+Basic @code{asm} statements are not treated as though they used a
"memory"
+clobber, although they do implicitly perform a clobber of the flags
+(@pxref{Clobbers}).
They do not clobber the flags.  Observe:

Ouch.  i386 shows the same thing for basic asm.
Sadly, I suspect this isn't consistent across targets.

Bigger ouch.  I'll follow up on this after the discussion about changing
basic asm is complete (which may render this moot).
It likely depends on how the target models the flags.

jeff


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]