On 2020-03-19 18:06, Michael Matz wrote: > 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.
Thanks. You bring up some good points which I hadn't yet considered, and I don't have any counter-arguments. So using the outputs on exception looks to be the best option then. I think the test cases can then also be reduced to a single function, as all operand types should behave the same. I will implement this and resubmit.