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.