https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82677

--- Comment #9 from infinity0 at pwned dot gg ---
(In reply to rguent...@suse.de from comment #7)
> [..]
> 
> You still have to mark stmts with side-effects as volatile.
> 
> Conditional side-effects are tricky to get correct of course.

I think with the current asm() syntax and semantics, the only way to get this
correct in the C source code, is by using __volatile__. It is not possible to
even *express* "conditional side-effects" using the current syntax. To
demonstrate:

The "explicit zero check" that I mentioned in the first post does not actually
work, see the newer udiv.c test that I just attached. I think that is correct
behaviour from GCC as well.

AIUI, asm() without volatile, says to GCC: "this code will *never* cause side
effects under *any circumstance*, it depends only on its declared
inputs/outputs/clobbers". Under this assumption, it is correct to optimise

|   if(d) { asm(d); ... } ...

into

|   asm(d); if(d) { ... }

as long as the outputs to asm(d) don't clobber the inputs to if(d) or any
else-branches - I assume other parts of the optimiser will already check that.

However, it is *not* correct to perform the above, when the asm(d) has
conditional side-effects depending on d, that the if(d) checks for. But there
is no way to express this conditional-side-effect using the current asm()
syntax. So GCC will happily go ahead and perform the optimisation, since it
believes asm(d) will never have any side effects.

So, the pre-optimised code "looks correct", it's explicitly checking d, but
will in fact cause the types of unintended optimisations that we're looking at
here. The only way to avoid this is to use "volatile".

In conclusion: whilst making the optimiser more strict for this case as you
suggested, would fix this specific instance, I believe that it is not "the
proper fix" for GCC. A proper fix would have to involve changing the
*semantics* of a asm(div) call so that GCC understands that it has "side
effects depending on the divisor and n1[1]". Otherwise, more sophisticated
optimisations added to GCC in the future might make this issue come back.

If that is not done, then it would be necessary to fix these 20 projects's C
source code to properly express __volatile__. Actually this is probably
necessary regardless of any GCC fixes - from some quick searches it seems that
asm() semantics is not standardised, and also these projects might want to
support older GCC that has the existing semantics.

[1] it can also raise DE when n1 >= divisor.

Reply via email to