On Wed, Mar 09, 2022 at 11:07:21AM +0100, Richard Biener wrote: > The following fixes an ICE observed with a MEM_REF allows_mem asm > operand. There's code expecting INDIRECT_REFs that are now never > going to appear. The following simply treats all tcc_reference > operands the same.
The INDIRECT_REF in there seems to be at least from 1995, but my limited understanding of what it wants to catch is operands that provably must live in memory. INDIRECT_REF (assuming *&*& is folded already) is such a case, MEM_REF could be but not always (there is the case of MEM_REF on &decl without TREE_ADDRESSABLE) but usually is, other handled_component_p depend on what their first operand is etc. I think there are two cases, one is an optimization (the && allows_mem case) where we don't want create a temporary (especially a huge one) if it clearly has to live in memory. Example where we mess this up: struct T { char b[1024]; }; struct S { int a; struct T b; } s; void foo (void) { asm volatile ("# %0" : : "rm" (s.b)); } where we create 1024 bytes long temporary on the stack, copy s.b to it and that is the operand live in memory. So perhaps for the allows_mem && case we could handle that way all BLKmode types (BLKmode must live in memory, no?) and otherwise look through all handled_component_p's and determine if the base will be in memory (addressable decl, MEM_REF except for ADDR of non-addressable decl, INDIRECT_REF, what else?). And another case is where it is not an optimization, where we just can't ever create a temporary. One of those examples is || TREE_ADDRESSABLE (type) the if already has, I guess non-constant length (ok, SVE is ok) would be another. assign_temp tests !poly_int_tree_p (TYPE_SIZE_UNIT (type), &size), so perhaps add || !tree_fits_poly_int64_p (TYPE_SIZE_UNIT (type)) ? Jakub