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.

Reply via email to