Hello,

On Wed, 18 Mar 2020, J.W. Jagersma via Gcc-patches wrote:

> > Well, it's both: on the exception path the compiler has to assume that the 
> > the value wasn't changed (so that former defines are regarded as dead) or 
> > that it already has changed (so that the effects the throwing 
> > "instruction" had on the result (if any) aren't lost).  The easiest for 
> > this is to regard the result place as also being an input.
> 
> The way I see it, there are two options: either you use the outputs
> when an exception is thrown, or you don't.

Assuming by "use the outputs" you mean "transform them implicitely to 
in-out operands", not "the source code uses the output operands after the 
asm on except and no-except paths".

> The first option is more or less what my first patch did, but it was
> incomplete.  Changing each output to in+out would make that work
> correctly.

Right.

> The second is what I have implemented now, each output is assigned via
> a temporary which is then assigned back to the variable bound to this
> output.  On exception, this temporary is discarded.  However this is
> not possible for asms that write directly to memory, so those cases are
> treated like option #1.

Right again, somewhat.  Except that the determination of which outputs are 
going into memory is a fuzzy notion until reload/LRA (which is very late 
in the compile pipeline).  You can infer some things from the constraint 
letters, but gimple might still put things into memory (e.g. when the 
output place is address taken), even though the constraint only allows a 
register (in which case reloads will be generated), or place something 
into a register, even though the constraint only allows memory (again, 
reloads will be generated).

Some of these reloads will be done early in the gimple pipeline to help 
optimizations (they basically look like the insns that you generate for 
copy-out), some of them will be generated only very late.

> I think the second option is easier on optimization since any previous
> assignments can be removed from the normal code path, and registers
> don't need to be loaded with known-valid values before the asm.

True (easier to optimizations) but immaterial (see below).

> The first option is more consistent since all outputs are treated the 
> same, but more dangerous, as the asm may write incomplete values before 
> throwing.

You have to assume that the author of the asm and its surrounding code is 
written by a knowledgable person, so if the asm possibly writes partially 
to outputs and then throws, then the output must not be accessed on the 
exception path.  If the asm does not write partially, then the author can 
access it.  So, what can or cannot be accessed on the exception path 
really is an inherent property of the contents of the asm.

Now, your second case tries to create additional guarantees: it makes it 
so that for some operands the user can depend on certain behaviour, namely 
that the old value before the asm was entered is available on the except 
path.  As you can't ensure this for all operands (those in memory are the 
problem) you want to tighten the definition to only include the operands 
where you can guarantee it, but this is fairly brittle, as above, because 
some decisions are taken very late.

There's another case to consider: assume I'm writing an asm that writes 
meaningful values to an output before and after a potential exception is 
thrown, ala this:

asm (" mov %2, %0
       xyz %2, %1
       mov $0, %0" : "=r" (status), "+r" (a) : "r" (b));

Assume 'xyz' can fault depending on input.  The intention above would be 
that on the exception path 'status' would contain a meaningful value (here 
the value of input b, and on the non-except path would contain zero.

Your proposal of copyin/out for register values would make the above 
impossible.  (Basically you wouldn't be able to output any reliable 
information out of the asm in the except path).

Given that, and the complication of determining what the safe-for-copy-out 
operands really are, and the fact that being easier on optimizations in 
connection with asms and -fnon-call-exceptions isn't a high priority it 
seems best to opt for the option that is guaranteed to work correctly in 
most cases, and in fact allows more freedom in using the asm.


Ciao,
Michael.

Reply via email to