Discussion:
Deprecating basic asm in a function - What now?
(too old to reply)
David Wohlferd
2016-06-20 06:43:00 UTC
Permalink
Perhaps this post should be directed toward port maintainers?

Since several global maintainers have now suggested it, I have created a
patch that deprecates basic asm when used in a function (attached). It
excludes (ie does not deprecate) top level asm, asm in "naked"
functions, asm with empty instruction strings, and extended asm.

Building gcc using this patch turns up a few places that use this
feature, so I fixed them. Where possible, I used builtins to replace
the asm. For ease-of-review, these changes are in their own patch
(attached) and obviously this patch should be checked in first.

But before I send these 2 off to gcc-patches, there's a problem. What
about platforms other than x86/x64? I don't speak other assembler
languages, and have no setup with which to test them.

I could try to provide patches for other platforms, but it would
probably be faster for platform experts to just make the changes
themselves, rather than trying to review my efforts. Especially if they
also want to move to builtins (which I hope they do).

I could just send the patches and let the chips fall where they may, but
if there's a less disruptive approach, let me know.

dw

PS I have done a scan for uses of basic asm to get some idea of the
scope of the remaining work. My results:

All basic asm in trunk: 1,105 instances.
- Exclude 273 instances with empty strings leaving 832.
- Exclude 271 instances for boehm-gc project leaving 561.
- Exclude 202 instances for testsuite project leaving 359.
- Exclude 282 instances that are (apparently) top-level leaving

~77 instances of basic-asm-in-a-function to be fixed for gcc builds.
Most of these are in gcc/config or libgcc/config with just a handful per
platform. Lists available upon request.

FWIW...
Andrew Pinski
2016-06-20 07:00:16 UTC
Permalink
Post by David Wohlferd
Perhaps this post should be directed toward port maintainers?
Since several global maintainers have now suggested it, I have created a
patch that deprecates basic asm when used in a function (attached). It
excludes (ie does not deprecate) top level asm, asm in "naked" functions,
asm with empty instruction strings, and extended asm.
Building gcc using this patch turns up a few places that use this feature,
so I fixed them. Where possible, I used builtins to replace the asm. For
ease-of-review, these changes are in their own patch (attached) and
obviously this patch should be checked in first.
But before I send these 2 off to gcc-patches, there's a problem. What about
platforms other than x86/x64? I don't speak other assembler languages, and
have no setup with which to test them.
I could try to provide patches for other platforms, but it would probably be
faster for platform experts to just make the changes themselves, rather than
trying to review my efforts. Especially if they also want to move to
builtins (which I hope they do).
I could just send the patches and let the chips fall where they may, but if
there's a less disruptive approach, let me know.
+ /* Acceptable. */
+ asm (" "); /* { dg-warning "Deprecated: asm in function without
extended syntax" } */

You say it is acceptable but then have a dg-warning on it.

Also I think the other place where we should accept basic asm is for
"nop" instructions. I have seen people use that heavily.

Note really I don't like the idea of deprecating basic asm at all.

Thanks,
Andrew
Post by David Wohlferd
dw
PS I have done a scan for uses of basic asm to get some idea of the scope of
All basic asm in trunk: 1,105 instances.
- Exclude 273 instances with empty strings leaving 832.
- Exclude 271 instances for boehm-gc project leaving 561.
- Exclude 202 instances for testsuite project leaving 359.
- Exclude 282 instances that are (apparently) top-level leaving
~77 instances of basic-asm-in-a-function to be fixed for gcc builds. Most
of these are in gcc/config or libgcc/config with just a handful per
platform. Lists available upon request.
FWIW...
Andrew Haley
2016-06-20 08:29:15 UTC
Permalink
Post by Andrew Pinski
+ /* Acceptable. */
+ asm (" "); /* { dg-warning "Deprecated: asm in function without
extended syntax" } */
This is incorrect English. It should be

"Deprecated: asm without extended syntax in function"

because it's the asm that is missing the extended syntax, not the
function.

Andrew.
Joseph Myers
2016-06-20 11:37:26 UTC
Permalink
Post by Andrew Haley
Post by Andrew Pinski
+ /* Acceptable. */
+ asm (" "); /* { dg-warning "Deprecated: asm in function without
extended syntax" } */
This is incorrect English. It should be
"Deprecated: asm without extended syntax in function"
No diagnostics should start with uppercase letters.

(I also disagree with the deprecation.)
--
Joseph S. Myers
***@codesourcery.com
Segher Boessenkool
2016-06-20 13:50:28 UTC
Permalink
Post by Andrew Pinski
Also I think the other place where we should accept basic asm is for
"nop" instructions. I have seen people use that heavily.
And anything else that means the same as basic asm and as extended asm.
Post by Andrew Pinski
Note really I don't like the idea of deprecating basic asm at all.
If basic asm is deprecated, that means some time later it will be
removed, at which time an asm without : can be used as extended asm
(or we can force everyone to write asm("nop":); if we are silly).

Warning about asm without : now is just unnecessary churn (and not just
for us, also for all the users of inline asm).


Segher
Andrew Haley
2016-06-20 13:55:58 UTC
Permalink
Post by Segher Boessenkool
If basic asm is deprecated, that means some time later it will be
removed, at which time an asm without : can be used as extended asm
Not exactly: it'd be an asm with no inputs, no outputs, and no
clobbers i.e. no effects.

Andrew.
Segher Boessenkool
2016-06-20 14:42:55 UTC
Permalink
Post by Andrew Haley
Post by Segher Boessenkool
If basic asm is deprecated, that means some time later it will be
removed, at which time an asm without : can be used as extended asm
Not exactly: it'd be an asm with no inputs, no outputs, and no
clobbers i.e. no effects.
I'm not sure what you mean? It will be treated exactly the same as
basic asm (it is now, anyway). And it has an effect, it is volatile
after all, not having any outputs?


Segher
Andrew Haley
2016-06-20 14:49:19 UTC
Permalink
Post by Segher Boessenkool
Post by Andrew Haley
Post by Segher Boessenkool
If basic asm is deprecated, that means some time later it will be
removed, at which time an asm without : can be used as extended asm
Not exactly: it'd be an asm with no inputs, no outputs, and no
clobbers i.e. no effects.
I'm not sure what you mean? It will be treated exactly the same as
basic asm (it is now, anyway). And it has an effect, it is volatile
after all, not having any outputs?
Well, you didn't say that it was volatile: and unless it really is
an asm volatile (not just an asm) an extended asm with no effects
is a statement with no effects.


Andrew.
Segher Boessenkool
2016-06-20 14:52:26 UTC
Permalink
Post by Andrew Haley
Post by Segher Boessenkool
Post by Andrew Haley
Post by Segher Boessenkool
If basic asm is deprecated, that means some time later it will be
removed, at which time an asm without : can be used as extended asm
Not exactly: it'd be an asm with no inputs, no outputs, and no
clobbers i.e. no effects.
I'm not sure what you mean? It will be treated exactly the same as
basic asm (it is now, anyway). And it has an effect, it is volatile
after all, not having any outputs?
Well, you didn't say that it was volatile: and unless it really is
an asm volatile (not just an asm) an extended asm with no effects
is a statement with no effects.
An extended asm without outputs is always volatile (exactly because
it would be useless otherwise).


Segher
Andrew Haley
2016-06-20 14:57:24 UTC
Permalink
Post by Segher Boessenkool
Post by Andrew Haley
Post by Segher Boessenkool
Post by Andrew Haley
Post by Segher Boessenkool
If basic asm is deprecated, that means some time later it will be
removed, at which time an asm without : can be used as extended asm
Not exactly: it'd be an asm with no inputs, no outputs, and no
clobbers i.e. no effects.
I'm not sure what you mean? It will be treated exactly the same as
basic asm (it is now, anyway). And it has an effect, it is volatile
after all, not having any outputs?
Well, you didn't say that it was volatile: and unless it really is
an asm volatile (not just an asm) an extended asm with no effects
is a statement with no effects.
An extended asm without outputs is always volatile (exactly because
it would be useless otherwise).
Oh, I see what you mean now. Yes, point taken.

Andrew.
DJ Delorie
2016-06-20 17:12:57 UTC
Permalink
Given how many embedded ports have #defines in external packages for
basic asms for instructions such as nop, enable/disable interrupts,
other system-level opcodes, etc... I think this is a bad idea. Even
glibc would break.

#define enable() asm("eint")

__asm__ __volatile__ ("fwait");
Michael Matz
2016-06-20 17:36:21 UTC
Permalink
Hi,
Post by David Wohlferd
All basic asm in trunk: 1,105 instances.
- Exclude 273 instances with empty strings leaving 832.
- Exclude 271 instances for boehm-gc project leaving 561.
- Exclude 202 instances for testsuite project leaving 359.
- Exclude 282 instances that are (apparently) top-level leaving
~77 instances of basic-asm-in-a-function to be fixed for gcc builds.
Most of these are in gcc/config or libgcc/config with just a handful per
platform. Lists available upon request.
Well, I think this quite clearly shows how bad an idea it would be to
deprecate basic asm. We are just one project, and ourself and our
dependencies already have 77+271 uses of them, not counting the testsuite
which also reflects some real world usage.

I see zero gain by deprecating them and only churn. What would be the
advantage again?


Ciao,
Michael.
Andrew Haley
2016-06-20 17:40:21 UTC
Permalink
Post by Michael Matz
I see zero gain by deprecating them and only churn. What would be the
advantage again?
Correctness. It is very likely that many of these basic asms are not
robust in the face of compiler changes because they don't declare
their dependencies and therefore work only by accident.

There are some correct basic asms. For example,

asm("nop")

There are some others too, once we've made the change to have basic
asms clobber memory. These include syscalls which are implemented
by using named register variables.

Andrew.
Michael Matz
2016-06-20 18:01:24 UTC
Permalink
Hi,
Post by Andrew Haley
Post by Michael Matz
I see zero gain by deprecating them and only churn. What would be the
advantage again?
Correctness.
As said in the various threads about basic asms, all correctness
problems can be solved by making GCC more conservative in handling them
(or better said: not making it less conservative).

If you talk about cases where basic asms diddle registers expecting GCC to
have placed e.g. local variables into specific ones (without using local
reg vars, or extended asm) I won't believe any claims ...
Post by Andrew Haley
It is very likely that many of these basic asms are not
robust
... of them being very likely without proof. They will have stopped
working with every change in compilation options or compiler version. In
contrast I think those that did survive a couple years in software very
likely _are_ correct, under the then documented (or implicit) assumptions.
Those usually are: clobbers and uses memory, processor state and fixed
registers.
Post by Andrew Haley
in the face of compiler changes because they don't declare their
dependencies and therefore work only by accident.
Then the compiler better won't change into less conservative handling of
basic asms.

You see, the experiment shows that there's a gazillion uses of basic asms
out there. Deprecating them means that each and every one of them (for us
alone that's 540 something, including testsuite and boehm) has to be
changed from asm("body") into asm("body" : : : "memory") (give and take
some syntax for also clobbering flags). Alternatively rewrite the
body to actually make use of extended asm. I guarantee you that a
non-trivial percentage will be wrong _then_ while they work fine now.
Even if it weren't so it still would be silly if GCC simply could regard
the former as the latter internally. It would just be change for the sake
of it and affecting quite many users without gain.


Ciao,
Michael.
Andrew Haley
2016-06-21 09:00:23 UTC
Permalink
Hi,
Post by Michael Matz
Post by Andrew Haley
Post by Michael Matz
I see zero gain by deprecating them and only churn. What would be the
advantage again?
Correctness.
As said in the various threads about basic asms, all correctness
problems can be solved by making GCC more conservative in handling them
(or better said: not making it less conservative).
Well, yes. That's exactly why we've agreed to change basic asms to
make them clobber memory, i.e. to make GCC more conservative.
Post by Michael Matz
If you talk about cases where basic asms diddle registers expecting GCC to
have placed e.g. local variables into specific ones (without using local
reg vars, or extended asm) I won't believe any claims ...
Post by Andrew Haley
It is very likely that many of these basic asms are not
robust
... of them being very likely without proof. They will have stopped
working with every change in compilation options or compiler
version. In contrast I think those that did survive a couple years
in software very likely _are_ correct, under the then documented (or
implicit) assumptions. Those usually are: clobbers and uses memory,
processor state and fixed registers.
Well, maybe. It's also fairly likely that many work by accident. IMO
this is more of a statement of hope than any kind of reasonable
expectation.
Post by Michael Matz
Post by Andrew Haley
in the face of compiler changes because they don't declare their
dependencies and therefore work only by accident.
Then the compiler better won't change into less conservative
handling of basic asms.
Repeat, repeat: the change being made is to make gcc MORE
conservative.
Post by Michael Matz
You see, the experiment shows that there's a gazillion uses of basic
asms out there. Deprecating them means that each and every one of
them (for us alone that's 540 something, including testsuite and
"memory") (give and take some syntax for also clobbering flags).
Alternatively rewrite the body to actually make use of extended asm.
I guarantee you that a non-trivial percentage will be wrong _then_
while they work fine now. Even if it weren't so it still would be
silly if GCC simply could regard the former as the latter
internally.
That's what we're doing.

Andrew.
Michael Matz
2016-06-21 12:08:26 UTC
Permalink
Hi,
Post by Michael Matz
As said in the various threads about basic asms, all correctness
problems can be solved by making GCC more conservative in handling
them (or better said: not making it less conservative).
Well, yes. That's exactly why we've agreed to change basic asms to make
them clobber memory, i.e. to make GCC more conservative.
Exactly. But this thread is about something else, see subject.
Well, maybe. It's also fairly likely that many work by accident. IMO
this is more of a statement of hope than any kind of reasonable
expectation.
Like yours, of course.
Post by Michael Matz
Then the compiler better won't change into less conservative handling
of basic asms.
Repeat, repeat: the change being made is to make gcc MORE
conservative.
This thread is about deprecating basic asms. That's not more
conservative, it's simply breaking backward compatibility for many users.
Post by Michael Matz
they work fine now. Even if it weren't so it still would be silly if
GCC simply could regard the former as the latter internally.
That's what we're doing.
Currently. But not the proposed patch in this thread, and the general
idea of deprecating the basic syntax.


Ciao,
Michael.
Andrew Haley
2016-06-21 16:33:09 UTC
Permalink
Hi,
Post by Michael Matz
Post by Michael Matz
As said in the various threads about basic asms, all correctness
problems can be solved by making GCC more conservative in handling
them (or better said: not making it less conservative).
Well, yes. That's exactly why we've agreed to change basic asms to make
them clobber memory, i.e. to make GCC more conservative.
Exactly. But this thread is about something else, see subject.
Well, you brought up the idea of making GCC "less conservative". But
making GCC less conservative is something that we have not agreed to
do. So why did you even mention it if it wasn't relevant?
Post by Michael Matz
Well, maybe. It's also fairly likely that many work by accident. IMO
this is more of a statement of hope than any kind of reasonable
expectation.
Like yours, of course.
Hmm. The problem is that programmers have false ideas about basic
asms. I was one of those programmers: I "knew" that basic asms
implicitly clobbered memory, and I was startled to find out I was
wrong. And I have been a GCC mainatiner for a long time. I guess it
is possible that all of those uses of basic asm David mentioned are in
fact correct. It's likely that adding a memory clobber will help.

But some things I have seen (such as changing the floating-point
status register) may not be be reliable without inputs and outputs and
should be fixed.

On the one hand we have the risk of churn, but basic asm in a function
isn't such a great idea anyway.

Andrew.
Jeff Law
2016-06-21 16:43:22 UTC
Permalink
Post by Andrew Haley
Hi,
Post by Michael Matz
Post by Michael Matz
As said in the various threads about basic asms, all correctness
problems can be solved by making GCC more conservative in handling
them (or better said: not making it less conservative).
Well, yes. That's exactly why we've agreed to change basic asms to make
them clobber memory, i.e. to make GCC more conservative.
Exactly. But this thread is about something else, see subject.
Well, you brought up the idea of making GCC "less conservative". But
making GCC less conservative is something that we have not agreed to
do. So why did you even mention it if it wasn't relevant?
I think there's enough resistance to deprecating basic asms within a
function that we should probably punt that idea.

I do think we should look to stomp out our own uses of basic asms within
functions just from a long term maintenance standpoint.

Finally I think we should continue to bring the implementation of basic
asms more in-line with expectations and future proofing them since I'm
having a hard time seeing a reasonable path to deprecating their use.

Jeff
Andrew Haley
2016-06-21 16:53:01 UTC
Permalink
Post by Jeff Law
I think there's enough resistance to deprecating basic asms within a
function that we should probably punt that idea.
I do think we should look to stomp out our own uses of basic asms
within functions just from a long term maintenance standpoint.
Finally I think we should continue to bring the implementation of
basic asms more in-line with expectations and future proofing them
since I'm having a hard time seeing a reasonable path to deprecating
their use.
Me too. I wonder if there's anything else we can do to make basic asm
in a function a bit less of a time bomb.

Andrew.
Florian Weimer
2016-06-22 09:02:50 UTC
Permalink
Post by Andrew Haley
Me too. I wonder if there's anything else we can do to make basic asm
in a function a bit less of a time bomb.
GCC could parse the assembly instructions and figure out the clobbers.

Florian
Manuel López-Ibáñez
2016-06-22 17:59:43 UTC
Permalink
Post by Florian Weimer
Post by Andrew Haley
Me too. I wonder if there's anything else we can do to make basic asm
in a function a bit less of a time bomb.
GCC could parse the assembly instructions and figure out the clobbers.
Which is also needed for various things, such as providing better diagnostics:

http://permalink.gmane.org/gmane.comp.compilers.llvm.cvs/70335
http://blog.llvm.org/2010/04/intro-to-llvm-mc-project.html
https://www.reddit.com/r/programming/comments/bnhxb/clang_now_with_inline_assembly_diagnostics/
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57950

Of course, that would require a closer integration with binutils. There has
been some work in that direction in the past:
https://sourceware.org/ml/binutils/2015-06/msg00010.html

but like the GCC-GDB integration, it seems to have stalled or be happening
behind closed doors.

Cheers,

Manuel.
Andrew Pinski
2016-06-22 18:05:48 UTC
Permalink
On Wed, Jun 22, 2016 at 10:59 AM, Manuel López-Ibáñez
Post by Manuel López-Ibáñez
Post by Florian Weimer
Post by Andrew Haley
Me too. I wonder if there's anything else we can do to make basic asm
in a function a bit less of a time bomb.
GCC could parse the assembly instructions and figure out the clobbers.
http://permalink.gmane.org/gmane.comp.compilers.llvm.cvs/70335
Actually GCC outputs markers that modern gas understands and you get
much better diagnostic already compared to what was reported above.
Note each target in gas has its own way of parsing assembly code which
is one of the reason why it is so hard todo the above and also each
target has its own wording which can confuse people. I think if you
want better diagnostic from assembly code, then working on binutils to
unify things including error messages (and subtarget support) would be
a much better use of time than integrating binutils into gcc.

Thanks,
Andrew
Post by Manuel López-Ibáñez
http://blog.llvm.org/2010/04/intro-to-llvm-mc-project.html
https://www.reddit.com/r/programming/comments/bnhxb/clang_now_with_inline_assembly_diagnostics/
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57950
Of course, that would require a closer integration with binutils. There has
https://sourceware.org/ml/binutils/2015-06/msg00010.html
but like the GCC-GDB integration, it seems to have stalled or be happening
behind closed doors.
Cheers,
Manuel.
Manuel López-Ibáñez
2016-06-22 19:26:16 UTC
Permalink
Post by Andrew Pinski
On Wed, Jun 22, 2016 at 10:59 AM, Manuel López-Ibáñez
Post by Manuel López-Ibáñez
Post by Florian Weimer
GCC could parse the assembly instructions and figure out the clobbers.
http://permalink.gmane.org/gmane.comp.compilers.llvm.cvs/70335
Actually GCC outputs markers that modern gas understands and you get
much better diagnostic already compared to what was reported above.
We get better diagnostics than in the past, but not as good as
Clang's. And there are many limitations of the "markers" approach: Not
only there is no column info, line info is often wrong:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57950

And there remains a lot of work to get GAS to output diagnostics like
GCC does nowadays (colors, caret, fix-it hints, etc.). And additional
work to make GAS obey GCC settings (if GCC disables colors, then GAS
should not output colors). Most of that work will be duplication of
what GCC already does.

Besides diagnostics, the integrated assembler is faster (as proven by
David Malcom's experiments) and it provides additional info to GCC
(the point raised by Florian).
Post by Andrew Pinski
Note each target in gas has its own way of parsing assembly code which
is one of the reason why it is so hard todo the above and also each
target has its own wording which can confuse people. I think if you
I didn't say it was easy. Yet, Clang/LLVM did it.
Post by Andrew Pinski
want better diagnostic from assembly code, then working on binutils to
unify things including error messages (and subtarget support) would be
a much better use of time than integrating binutils into gcc.
Unifying error messages does not seem to be a feature used to
advertise Clang as a replacement for GCC. It doesn't seem to be what
users discuss in various forums (including the reddit thread I quoted
above). It won't help with the issues discussed in this thread.

Cheers,

Manuel.
Andrew Pinski
2016-06-22 19:28:14 UTC
Permalink
On Wed, Jun 22, 2016 at 12:26 PM, Manuel López-Ibáñez
Post by Manuel López-Ibáñez
Post by Andrew Pinski
On Wed, Jun 22, 2016 at 10:59 AM, Manuel López-Ibáñez
Post by Manuel López-Ibáñez
Post by Florian Weimer
GCC could parse the assembly instructions and figure out the clobbers.
http://permalink.gmane.org/gmane.comp.compilers.llvm.cvs/70335
Actually GCC outputs markers that modern gas understands and you get
much better diagnostic already compared to what was reported above.
We get better diagnostics than in the past, but not as good as
Clang's. And there are many limitations of the "markers" approach: Not
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57950
And there remains a lot of work to get GAS to output diagnostics like
GCC does nowadays (colors, caret, fix-it hints, etc.). And additional
work to make GAS obey GCC settings (if GCC disables colors, then GAS
should not output colors). Most of that work will be duplication of
what GCC already does.
Besides diagnostics, the integrated assembler is faster (as proven by
David Malcom's experiments) and it provides additional info to GCC
(the point raised by Florian).
Post by Andrew Pinski
Note each target in gas has its own way of parsing assembly code which
is one of the reason why it is so hard todo the above and also each
target has its own wording which can confuse people. I think if you
I didn't say it was easy. Yet, Clang/LLVM did it.
That is because there are less targets on the Clang/LLVM side of things.
Post by Manuel López-Ibáñez
Post by Andrew Pinski
want better diagnostic from assembly code, then working on binutils to
unify things including error messages (and subtarget support) would be
a much better use of time than integrating binutils into gcc.
Unifying error messages does not seem to be a feature used to
advertise Clang as a replacement for GCC. It doesn't seem to be what
users discuss in various forums (including the reddit thread I quoted
above). It won't help with the issues discussed in this thread.
Cheers,
Manuel.
Manuel López-Ibáñez
2016-06-22 19:34:48 UTC
Permalink
Post by Andrew Pinski
On Wed, Jun 22, 2016 at 12:26 PM, Manuel López-Ibáñez
Post by Manuel López-Ibáñez
Post by Andrew Pinski
Note each target in gas has its own way of parsing assembly code which
is one of the reason why it is so hard todo the above and also each
target has its own wording which can confuse people. I think if you
I didn't say it was easy. Yet, Clang/LLVM did it.
That is because there are less targets on the Clang/LLVM side of things.
And not even all of them have an integrated assembler. Yet, having it
for the most popular targets is enough. Having the infrastructure in
place is far more important, since it allows people interested in the
less popular ones to do the work necessary to implement it.

Cheers,

Manuel.
David Wohlferd
2016-06-22 09:28:57 UTC
Permalink
Post by Jeff Law
I think there's enough resistance to deprecating basic asms within a
function that we should probably punt that idea.

I don't disagree that there has been pushback. I just wish less of it
was of the form "Because I don't wanna." A few examples of "Here's
something that has to be in basic asm because..." might have produced a
more interesting discussion. I think if people had to defend (even to
themselves) why they were using BAIF, there might be more converts.

And I *get* that it takes time to re-write this, and people have
schedules, lives, a need for sleep. But even under the most insanely
aggressive schedule I can imagine (if gcc continue to release ~1/year),
it will be at least a year before there's a release that has the
(disable-able) warning, and another year before we could even think
about actually removing this. So someone who plans to use v8.0 in their
production code on the day it is released still has a minimum of *two
years* to get ready.
Post by Jeff Law
I do think we should look to stomp out our own uses of basic asms
within functions just from a long term maintenance standpoint.

Fixes.patch (from the start of this thread) seems mostly uncontested.
Send it to patches?

If someone wanted to clean up a bunch of these, they should take a look
at CRT_CALL_STATIC_FUNCTION in gcc/config. This is defined for nearly
every platform, and most of them do it with basic asm. I gotta wonder
if there's a better way to do this. Isn't there an attribute for 'section'?
Post by Jeff Law
Finally I think we should continue to bring the implementation of
basic asms more in-line with expectations and future proofing them

I believe there are compilers that do safely use inline asm. However it
appears that they accomplish this trick by parsing the asm. Not
something I expect to see added to gcc anytime soon...
Post by Jeff Law
since I'm having a hard time seeing a reasonable path to deprecating
their use.

Umm. Hmm. Seems like the ideal answer here would be something that
prevents new code from using BAIF, without putting the old-timers in an
uproar.

So how about the old "empty threat" gambit? We could *say* we are going
to deprecate it, put the (disable-able) warning into the code and the
stern-sounding text in the docs, and then *leave* it like that for a
decade or so. The idea being that new code won't use it, but old code
will still be supported. Hopefully 10 years from now, there might be so
little code that uses BAIF that finally removing it may no longer be so
controversial. It's not a lie, since deprecate means "express
disapproval of" and yeah, that's about right. And since we don't
specify precisely *when* we intend to remove it...

dw
Andrew Haley
2016-07-04 13:44:21 UTC
Permalink
It doesn't matter how much warning people have to fix such things,
most of them won't do it. Then at the last minute some poor person has
to spend days or weeks going through other people's code fixing all
the problems...
...and breaking everything.

Andrew.
Frank Ch. Eigler
2016-07-04 16:09:47 UTC
Permalink
[...] (When we switched Fedora to using GCC 6, with C++14 enabled by
default, dozens and dozens of C++ packages failed to compile,
because even in 2016 nobody had ever tried to compile them with
C++11 features enabled.)
And one shouldn't blame those that choose to stick with CXXFLAGS=-std=c++98
instead of porting their code, which after all is working & stable.

- FChE
Jason Merrill
2016-07-05 18:13:12 UTC
Permalink
Post by Frank Ch. Eigler
[...] (When we switched Fedora to using GCC 6, with C++14 enabled by
default, dozens and dozens of C++ packages failed to compile,
because even in 2016 nobody had ever tried to compile them with
C++11 features enabled.)
And one shouldn't blame those that choose to stick with CXXFLAGS=-std=c++98
instead of porting their code, which after all is working & stable.
Absolutely, that's a fine solution. Though often it makes sense to
put the -std argument in the CXX variable rather than CXXFLAGS.

Jason

Toon Moene
2016-07-05 17:52:03 UTC
Permalink
And I *get* that it takes time to re-write this, and people have schedules,
lives, a need for sleep. But even under the most insanely aggressive
schedule I can imagine (if gcc continue to release ~1/year), it will be at
least a year before there's a release that has the (disable-able) warning,
and another year before we could even think about actually removing this.
So someone who plans to use v8.0 in their production code on the day it is
released still has a minimum of *two years* to get ready.
It doesn't matter how much warning people have to fix such things,
most of them won't do it. Then at the last minute some poor person has
to spend days or weeks going through other people's code fixing all
the problems. If the benefit isn't clear then it's just a pain and
causes wailing and gnashing of teeth.
We had at least 15 years of warning ahead of the Y2K problem.
Nevertheless, it was only fixed in our code during March-September 1999.

Or, as one of my colleagues quipped: The next time, they can ask someone
else for this job.
--
Toon Moene - e-mail: ***@moene.org - phone: +31 346 214290
Saturnushof 14, 3738 XG Maartensdijk, The Netherlands
At home: http://moene.org/~toon/; weather: http://moene.org/~hirlam/
Progress of GNU Fortran: http://gcc.gnu.org/wiki/GFortran#news
David Wohlferd
2016-06-22 09:23:46 UTC
Permalink
In the end, my problems with basic-asm-in-functions (BAIF) come down to
reliably generating correct code.

Optimizations are based on the idea of "you can safely modify x if you
can prove y." But given that basic asm are opaque blocks, there is no
way to prove, well, much of anything. Adding 'volatile' and now
'memory' do help. But the very definition of "opaque blocks" means that
you absolutely cannot know what weird-ass crap someone might be trying.
And every time gcc tweaks any of the optimizers, there's a chance that
this untethered blob could bubble up or down within the code. There is
no way for any optimizer to safely decide whether a given position
violates the intent of the asm, since it can have no idea what that
intent is. Can even a one line displacement of arbitrary assembler code
cause race conditions or data corruption without causing a compiler
error? I'll bet it can.

And also, there is the problem of compatibility. I am told that the
mips "sync" instruction (used in multi-thread programming) requires a
memory clobber to work as intended. With that in mind, when I see this
code on some blog, is it safe?

asm("sync");

And of course the answer is that without context, there's no way to
know. It might have been safe for the compiler in the blogger's
environment. Or maybe he was an idiot. It's certainly not safe in any
released version of gcc. But unless the blog reader knows the blogger's
level of intelligence, development environment, and all the esoteric
differences between that environment and their own, they could easily
copy/paste that right into their own project, where it will compile
without error, and "nearly always" work just fine...

With Bernd's recent change, people who have this (incorrect) code in
their gcc project will suddenly have their code start working correctly,
and that's a good thing. Well, they will a year or so from now. If
they immediately start using v7.0. And if they prevent everyone from
trying to compile their code using 6.x, 5.x, 4.x etc where it will never
work correctly. So yes, it's a fix. But it can easily be years before
this change finally solves this problem. However, changing this to use
extended:

asm("sync":::"memory");

means that their very next source code release will immediately work
correctly on every version of gcc.

You make the point about how people changing this code could easily muck
things up. And I absolutely agree, they could. On the other hand, it's
possible that their code is already mucked up and they just don't know
it. But even if they change this code to asm("sync":::) (forcing it to
continue working the same way it has for over a decade), the
programmer's intent is clear (if wrong). A knowledgeable mips
programmer could look at that and say "Hey, that's not right." While
making that same observation with asm("sync") is all but impossible.

BAIF is fragile. That, combined with: unmet user expectations, bad user
code, inconsistent implementations between compilers, changing
implementations within compilers, years of bad docs, no "best practices"
guide and an area that is very complex all tell me that this is an area
filled with unfixable, ticking bombs. That's why I think it should be
deprecated.
Post by Michael Matz
Post by Andrew Haley
Post by Michael Matz
I see zero gain by deprecating them and only churn. What would be the
advantage again?
Correctness.
As said in the various threads about basic asms, all correctness
problems can be solved by making GCC more conservative in handling them
(or better said: not making it less conservative).
If you talk about cases where basic asms diddle registers expecting GCC to
have placed e.g. local variables into specific ones (without using local
reg vars, or extended asm) I won't believe any claims ...
Post by Andrew Haley
It is very likely that many of these basic asms are not
robust
... of them being very likely without proof.
I don't have a sample of people accessing local variables, but I do have
one where someone was using 'scratch' registers in BAIF assuming the
compiler would just "handle it." And before you call that guy a dummy,
let me point out that under some compilers, that's a perfectly valid
assumption for asm. And even if not, it may have been working "just
fine" in his implementation for years. Which doesn't make it right.
Post by Michael Matz
They will have stopped
working with every change in compilation options or compiler version. In
contrast I think those that did survive a couple years in software very
likely _are_ correct, under the then documented (or implicit) assumptions.
Those usually are: clobbers and uses memory, processor state and fixed
registers.
As I was saying, a history of working doesn't make it right. It just
means the ticking hasn't finished yet.

How would you know if you have correctly followed the documented rules?
Don't expect the compiler to flag these violations for you.
Post by Michael Matz
Post by Andrew Haley
in the face of compiler changes because they don't declare their
dependencies and therefore work only by accident.
Then the compiler better won't change into less conservative handling of
basic asms.
You see, the experiment shows that there's a gazillion uses of basic asms
out there. Deprecating them means that each and every one of them (for us
alone that's 540 something, including testsuite and boehm) has to be
changed from asm("body") into asm("body" : : : "memory") (give and take
some syntax for also clobbering flags). Alternatively rewrite the
body to actually make use of extended asm. I guarantee you that a
non-trivial percentage will be wrong _then_ while they work fine now.
Yes, that sounds bad, and you aren't wrong.

On the other hand, there is no guarantee that they are actually correct
right now. Correct enough? Maybe so. But of course there's no
guarantee that tomorrow's newest optimization won't bork some of them
because it followed the rules and you didn't quite.

And if we're talking about made up numbers, what about the 'non-trivial'
percentage of changes that end up improving things? Fixing bugs, better
performance, more maintainable code, optimization failures and late
night debugging sessions that never happen, etc...
Post by Michael Matz
Even if it weren't so it still would be silly if GCC simply could regard
the former as the latter internally. It would just be change for the sake
of it and affecting quite many users without gain.
Ciao,
Michael.
Jakub Jelinek
2016-06-22 09:39:21 UTC
Permalink
I don't have a sample of people accessing local variables, but I do have one
where someone was using 'scratch' registers in BAIF assuming the compiler
would just "handle it." And before you call that guy a dummy, let me point
out that under some compilers, that's a perfectly valid assumption for asm.
And even if not, it may have been working "just fine" in his implementation
for years. Which doesn't make it right.
And how would deprecation of basic asm help with that?
People can as well use 'scratch' registers in extended asm without
mentioning them in outputs or clobbers (and there are many real-world
examples of that that sometimes happen to "work" by accident).
On the other hand, there is no guarantee that they are actually correct
right now. Correct enough? Maybe so. But of course there's no guarantee
that tomorrow's newest optimization won't bork some of them because it
followed the rules and you didn't quite.
You don't have such guarantee for extended asm either, lots of
them are just ticking bombs that will fail when anything in the compiler is
changed.

Jakub
James Greenhalgh
2016-06-22 15:23:35 UTC
Permalink
Post by Michael Matz
You see, the experiment shows that there's a gazillion uses of basic asms
out there.
I applied the proposed patch and built myself an allyesconfig AArch64 linux
kernel, the results were not pretty...

make | grep "warning: Deprecated: asm" | wc -l
8911

You could say I'm cheating as the asm in question appears in header files,
but this would be more than enough noise to guarantee the kernel will be
built with your warning disabled (and when the Linux kernel switches a
warning off, history suggests it won't be coming back on!). Remember that
while you might convince people to apply the proper fix for kernel version
N, you might struggle to get that fix backported across stable releases,
vendor releases, private releases etc. particularly when the alternative
fix of silencing the warning will appear to work fine.

There are 11 unique warnings for an arm64 Linux kernel build, 7 unique
warnings for an arm kernel build and 369 unique warnings for an x86_64
kernel build. Just for fun I counted how many warnings I get with x86_64
allyesconfig without filtering for unique; 14,697.

I haven't audited them to see which would be safe with the minimal changes
given in https://gcc.gnu.org/wiki/ConvertBasicAsmToExtended (that document
looks buggy, should it not reccommend that you always add a volatile when
moving from basic to extended?). The sorts of things I see in the arm/arm64
port are sleep loops for CPUs guarded by a conditional, asm guarded by other
asm barriers, text added to mergeable read-only section for common strings,
other things that are not obviously broken uses of basic asm.

On the other hand, some of the the x86_64 examples in lib/raid6/sse2.c are
super scary and have back-to-back instructions with hard-coded registers...

asm volatile("pcmpgtb %xmm4,%xmm5");
asm volatile("paddb %xmm4,%xmm4");
asm volatile("pand %xmm0,%xmm5");

I can't defend them, and they look very fragile! Fixing this code would
require more substantial work.

I'm only looking at one consumer of our compiler here, but I think anything
that would cause the kernel community this much pain is a risky move, and is
indicative of how frequently we'd see this warning fire in the wild.
Permanently removing basic asm in a future GCC version is certainly not a
workable solution. So what is the value of a noisy warning?

Jeff and others have already come out against this patch, I'd like to add
my vote against it too.

Thanks,
James
Jeff Law
2016-06-22 16:50:11 UTC
Permalink
Post by James Greenhalgh
On the other hand, some of the the x86_64 examples in lib/raid6/sse2.c are
super scary and have back-to-back instructions with hard-coded registers...
asm volatile("pcmpgtb %xmm4,%xmm5");
asm volatile("paddb %xmm4,%xmm4");
asm volatile("pand %xmm0,%xmm5");
I can't defend them, and they look very fragile! Fixing this code would
require more substantial work.
Yow! This kind of crap is all over that file. Fragile indeed!
Post by James Greenhalgh
Jeff and others have already come out against this patch, I'd like to add
my vote against it too.
To be clear, given all I've seen I would actively object at this point.
We can't inflict this much pain on the user base.

jeff
Florian Weimer
2016-06-22 08:59:40 UTC
Permalink
Post by Andrew Haley
Post by Michael Matz
I see zero gain by deprecating them and only churn. What would be the
advantage again?
Correctness. It is very likely that many of these basic asms are not
robust in the face of compiler changes because they don't declare
their dependencies and therefore work only by accident.
But the correctness problem is much more severe with extended asm. With
basic asm, the compiler can be conservative. With extended asm, there
is an expectation that it is not, and yet many of the constraints out
there are slightly wrong and can lead to breakage any time.

Florian
Andrew Haley
2016-06-22 10:45:40 UTC
Permalink
Post by Florian Weimer
Post by Andrew Haley
Post by Michael Matz
I see zero gain by deprecating them and only churn. What would be the
advantage again?
Correctness. It is very likely that many of these basic asms are not
robust in the face of compiler changes because they don't declare
their dependencies and therefore work only by accident.
But the correctness problem is much more severe with extended asm. With
basic asm, the compiler can be conservative. With extended asm, there
is an expectation that it is not, and yet many of the constraints out
there are slightly wrong and can lead to breakage any time.
Yes, that's true. However, at least in the case of extended asm there
is a chance that the programmer has thought about it.

But anyway, the decision has been made. None of this matters.

Andrew.
Bernd Edlinger
2016-06-21 18:29:45 UTC
Permalink
Post by Andrew Haley
Post by Jeff Law
I think there's enough resistance to deprecating basic asms within a
function that we should probably punt that idea.
I do think we should look to stomp out our own uses of basic asms
within functions just from a long term maintenance standpoint.
Finally I think we should continue to bring the implementation of
basic asms more in-line with expectations and future proofing them
since I'm having a hard time seeing a reasonable path to deprecating
their use.
Me too. I wonder if there's anything else we can do to make basic asm
in a function a bit less of a time bomb.
Andrew.
I do not like the idea to deprecate the basic asm at all, I must admit,
but I think if we added a warning, that just contains a positive information, like
"warning: basic asm semantic has been changed to implicitly clobber memory,
if you have a problem with that, please convert this asm statement to extended
asm syntax."

Then that would possibly be acceptable for everybody here.

We could still discuss, if that warning should be enabled with -Wall, -Wextra or only
on request.


Bernd.
Jakub Jelinek
2016-06-21 19:31:00 UTC
Permalink
Post by Bernd Edlinger
I do not like the idea to deprecate the basic asm at all, I must admit,
but I think if we added a warning, that just contains a positive information, like
"warning: basic asm semantic has been changed to implicitly clobber memory,
if you have a problem with that, please convert this asm statement to extended
asm syntax."
I don't see any point of such a warning.

And, I agree that deprecation of basic asm is a bad idea.

Jakub
Continue reading on narkive:
Loading...