gcc.dg/atomic/c11-atomic-exec-1.c has been failing at -O2 -mcpu=v8 on SPARC 
since the fix for PR middle-end/61268 was installed, i.e. with all 5.x, 6.x 
and 7.0 compilers.  The failure mode is as follows:

emit_cstore is called on:

(mem/c:DF (plus:SI (plus:SI (reg/f:SI 104 virtual-stack-vars)
            (reg:SI 1753))
        (const_int 8 [0x8])) [2 D.1567+8 S8 A64])

and does:

    last = get_last_insn ();

then it calls prepare_operand, which calls copy_to_mode_reg, which calls 
emit_move_insn, which calls validize_mem, which modifies the MEM in-place:

(mem/c:DF (plus:SI (reg/f:SI 1757)
        (const_int 8 [0x8])) [2 D.1567+8 S8 A64])

after emitting an addition:

(set (reg/f:SI 1757)
     (plus:SI (reg/f:SI 104 virtual-stack-vars) (reg:SI 1753)))

But the call to maybe_expand_insn from emit_cstore fails so:

     delete_insns_since (last);

is invoked and the addition is lost, i.e. (reg/f:SI 1757) will be emitted
uninitialized in the RTL stream, leading to a SIGSEGV at run time.

IMO this shows that the explow.c hunk of the fix for PR middle-end/61268 was 
ill-advised and should not have been accepted.  Having copy_to_mode_reg or 
emit_move_insn silently modify their argument is IMO a recipe for problems.

So the attached patch backs it out and I suggest installing on all branches.

Tested on x86_64-suse-linux.

2016-10-15  Eric Botcazou  <ebotca...@adacore.com>

        * explow.c (validize_mem): Do not modify the argument in-place.

Eric Botcazou
Index: explow.c
--- explow.c	(revision 241147)
+++ explow.c	(working copy)
@@ -496,9 +496,8 @@ memory_address_addr_space (machine_mode
   return x;
-/* If REF is a MEM with an invalid address, change it into a valid address.
-   Pass through anything else unchanged.  REF must be an unshared rtx and
-   the function may modify it in-place.  */
+/* Convert a mem ref into one with a valid memory address.
+   Pass through anything else unchanged.  */
 validize_mem (rtx ref)
@@ -510,7 +509,8 @@ validize_mem (rtx ref)
 				   MEM_ADDR_SPACE (ref)))
     return ref;
-  return replace_equiv_address (ref, XEXP (ref, 0), true);
+  /* Don't alter REF itself, since that is probably a stack slot.  */
+  return replace_equiv_address (ref, XEXP (ref, 0));
 /* If X is a memory reference to a member of an object block, try rewriting

Reply via email to