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?



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
+  /* 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

Reply via email to