https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67653
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jakub at gcc dot gnu.org --- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Bet r140431. The issue seems to be that the FEs make the "m" operand addressable: if (parse_output_constraint (&constraint, i, ninputs, noutputs, &allows_mem, &allows_reg, &is_inout)) { /* If the operand is going to end up in memory, mark it addressable. */ if (!allows_reg && !cxx_mark_addressable (operand)) operand = error_mark_node; } or: if (!allows_reg && allows_mem) { input = c_fully_fold (input, false, NULL); /* Strip the nops as we allow this case. FIXME, this really should be rejected or made deprecated. */ STRIP_NOPS (input); if (!c_mark_addressable (input)) input = error_mark_node; } but for the case of a statement expression that doesn't mark it addressable. Then during gimplify_asm_expr we: 5281 tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p, 5282 is_gimple_lvalue, fb_lvalue | fb_mayfail); 5283 mark_addressable (TREE_VALUE (link)); 5284 if (tret == GS_ERROR) and in this case tref actually is not GS_ERROR, as it is gimplified to an artificial decl from a TARGET_EXPR. But it marks addressable something that has been already used. No idea what to do here. For "=m" we require lvalue_or_else (after doing a hack and stripping nops), but for the input operands we don't. So perhaps just replace the mark_addressable call with something like: tree x = TREE_VALUE (link); while (handled_component_p (x)) x = TREE_OPERAND (x, 0); if (TREE_CODE (x) == MEM_REF && TREE_CODE (TREE_OPERAND (x, 0)) == ADDR_EXPR) x = TREE_OPERAND (TREE_OPERAND (x, 0), 0); if ((TREE_CODE (x) == VAR_DECL || TREE_CODE (x) == PARM_DECL || TREE_CODE (x) == RESULT_DECL) && !TREE_ADDRESSABLE (x)) { error ("memory input %d is not directly addressable", i); ret = GS_ERROR; }