Hi, when testing a patch of mine on sparc64-linux, I came across an Ada bootstrap failure due to a structure DECL which was marked addressable but had a register DECL_RTL (and therefore mem_ref_refers_to_non_mem_p failed to trigger on it).
Mode of the structure was TI (16 bytes int) and it was mistakenly marked as addressable during expansion of an assignment statement in which a 12 byte portion of it was copied to another structure with BLKmode. Specifically, this happened because expand_assignment called store_expr which loaded the required portion to temporary 12 byte BLKmode MEM_P variable and then called emit_block_move from the temporary to the destination. emit_block_move_hints then marked MEM_EXPR of the temp as addressable because it handled the copy by emitting a library call. And MEM_EXPR pointed to the DECL of the source of the assignment which I believe is the bug, thus this patch re-sets MEM_EXPR of temp in these cases. However, if anybody believes the main issue is elsewhere and another component of this chain of events needs to be fixed, I'll be happy to come up with another patch. so far this patch has passed bootstrap and testing on x86_64-linux and helped my patch which uncovered this issue to reach stage 3 of bootstrap. What do you think, is it OK for trunk? Thanks, Martin 2012-03-30 Martin Jambor <mjam...@suse.cz> * expr.c (non_mem_decl_p): New function with half of previous functionality of... (mem_ref_refers_to_non_mem_p): ...this one. (store_expr): Reset MEM_EXPR of temp if it refers to memory but the original expression is based on a non-memory based declaration. Index: src/gcc/expr.c =================================================================== --- src.orig/gcc/expr.c +++ src/gcc/expr.c @@ -4479,6 +4479,24 @@ get_bit_range (unsigned HOST_WIDE_INT *b *bitend = *bitstart + tree_low_cst (DECL_SIZE (repr), 1) - 1; } +/* Returns true if T is a DECL that does not reside in a memory and has a + non-BLK mode. */ + +static bool +non_mem_decl_p (tree t) +{ + if (!DECL_P (t)) + return false; + gcc_checking_assert (!TREE_ADDRESSABLE (t) + || !DECL_RTL_SET_P (t) + || MEM_P (DECL_RTL (t))); + return (!TREE_ADDRESSABLE (t) + && DECL_MODE (t) != BLKmode + && DECL_RTL_SET_P (t) + && !MEM_P (DECL_RTL (t))); +} + + /* Returns true if the MEM_REF REF refers to an object that does not reside in memory and has non-BLKmode. */ @@ -4489,11 +4507,7 @@ mem_ref_refers_to_non_mem_p (tree ref) if (TREE_CODE (base) != ADDR_EXPR) return false; base = TREE_OPERAND (base, 0); - return (DECL_P (base) - && !TREE_ADDRESSABLE (base) - && DECL_MODE (base) != BLKmode - && DECL_RTL_SET_P (base) - && !MEM_P (DECL_RTL (base))); + return non_mem_decl_p (base); } /* Expand an assignment that stores the value of FROM into TO. If NONTEMPORAL @@ -5105,6 +5119,16 @@ store_expr (tree exp, rtx target, int ca &alt_rtl); } + /* When the original expression is a declaration not residing in memory but + temp is a MEM RTX, we must dissociate it from the original expression or + emit_block_move might mark it as addressable. */ + if (MEM_P (temp)) + { + tree base = get_base_address (exp); + if (base && non_mem_decl_p (base)) + set_mem_expr (temp, NULL_TREE); + } + /* If TEMP is a VOIDmode constant and the mode of the type of EXP is not the same as that of TARGET, adjust the constant. This is needed, for example, in case it is a CONST_DOUBLE and we want only a word-sized