On 2020-03-12 10:59, Richard Sandiford wrote:
> The other case I mentioned was equivalent to:
>
> int
> test_mem2 ()
> {
> int i = 2;
> try
> {
> asm volatile ("ud2; mov%z0 $1, %0" : "=m" (i));
> }
> catch (const illegal_opcode&)
> {
> if (i == 2) return 0;
> }
> return i;
> }
>
> Is this test expected to pass?
Good point. Yes, this should pass, and I thought it did, but it seems
I was mistaken. To fix that would require transforming "=m" into "+m"
as Segher suggested.
> However, these "mem" tests are testing gimple register types, so they'll
> still be SSA names outside of the asm. It would also be good to test what
> happens for non-register types, e.g. something like:
>
> int
> test_mem3 ()
> {
> int i[5] = { 1, 2, 3, 4, 5 };
> try
> {
> asm volatile ("ud2; <insert asm here>" : "=m" (i));
> }
> catch (const illegal_opcode&)
> {
> if (i[0] == 1 && ...) return 0;
> }
> return ...;
> }
>
> and similarly for ud2 after the store.
I think I see what you mean. Would such a test not also cover what the
current test_mem() function does? If so then that could be removed.
Also in my current patch I used: (tree-eh.c:2104)
if (tree_could_throw_p (opval)
|| !is_gimple_reg_type (TREE_TYPE (opval))
|| !is_gimple_reg (get_base_address (opval)))
to determine the difference between a register and memory type. Could
there potentially be a case where that identifies an operand as gimple
register type, but ends up compiled as a memory operand to an asm?
> It wasn't clear from my message above, but: I was mostly worried about
> requiring the asm to treat memory operands in a certain way when the
> exception is thrown. IMO it would be better to say that the values of
> memory operands are undefined on the exception edge.
I'm not sure about the semantic difference between undefined and
unspecified. But gcc should not write to any memory after a throw,
because that write operation itself may have side effects. Likewise
asm memory operands should not be redirected to a temporary for the
same reason, and also because gcc can't possibly know which parts of
an (offsettable) memory operand are written to.