sparc.md (UNSPEC_FRAME_BLOCKAGE): New constant.
authorEric Botcazou <ebotcazou@adacore.com>
Fri, 16 Dec 2011 23:37:48 +0000 (23:37 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Fri, 16 Dec 2011 23:37:48 +0000 (23:37 +0000)
* config/sparc/sparc.md (UNSPEC_FRAME_BLOCKAGE): New constant.
(frame_blockage): New expander.
(frame_blockage<P:mode>): New instruction.
* config/sparc/sparc.c (sparc_expand_prologue): When the sequence of
instructions establishing the frame isn't atomic, emit frame blockage.

From-SVN: r182420

gcc/ChangeLog
gcc/config/sparc/sparc.c
gcc/config/sparc/sparc.md

index 58498616ab22d67dc0ad78faf6bfff646fd42512..1c8b3a20c890567e6210c947dc4bda7bd3eb52cd 100644 (file)
@@ -1,3 +1,11 @@
+2011-12-16  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * config/sparc/sparc.md (UNSPEC_FRAME_BLOCKAGE): New constant.
+       (frame_blockage): New expander.
+       (frame_blockage<P:mode>): New instruction.
+       * config/sparc/sparc.c (sparc_expand_prologue): When the sequence of
+       instructions establishing the frame isn't atomic, emit frame blockage.
+
 2011-12-16  Tristan Gingold  <gingold@adacore.com>
 
        * config/alpha/vms.h (USE_TM_CLONE_REGISTRY): Define.
index 20efb00c4517fb43ff599d84d4e4d4e796f77a6b..19ab54a1304f6916344ec294d7cd29f0f05ad977 100644 (file)
@@ -4972,8 +4972,9 @@ sparc_expand_prologue (void)
       else if (size <= 8192)
        {
          insn = emit_insn (gen_stack_pointer_inc (GEN_INT (-4096)));
-         /* %sp is still the CFA register.  */
          RTX_FRAME_RELATED_P (insn) = 1;
+
+         /* %sp is still the CFA register.  */
          insn = emit_insn (gen_stack_pointer_inc (GEN_INT (4096 - size)));
        }
       else
@@ -4996,8 +4997,18 @@ sparc_expand_prologue (void)
       else if (size <= 8192)
        {
          emit_window_save (GEN_INT (-4096));
+
          /* %sp is not the CFA register anymore.  */
          emit_insn (gen_stack_pointer_inc (GEN_INT (4096 - size)));
+
+         /* Make sure no %fp-based store is issued until after the frame is
+            established.  The offset between the frame pointer and the stack
+            pointer is calculated relative to the value of the stack pointer
+            at the end of the function prologue, and moving instructions that
+            access the stack via the frame pointer between the instructions
+            that decrement the stack pointer could result in accessing the
+            register window save area, which is volatile.  */
+         emit_insn (gen_frame_blockage ());
        }
       else
        {
index 37ac1701b69559ab1887322276edb7545d08f686..f67ee83d048aca4334c44760710b30fc80e4f614 100644 (file)
@@ -28,6 +28,7 @@
   [(UNSPEC_MOVE_PIC            0)
    (UNSPEC_UPDATE_RETURN       1)
    (UNSPEC_LOAD_PCREL_SYM      2)
+   (UNSPEC_FRAME_BLOCKAGE      3)
    (UNSPEC_MOVE_PIC_LABEL      5)
    (UNSPEC_SETH44              6)
    (UNSPEC_SETM44              7)
   ""
   [(set_attr "length" "0")])
 
+;; Do not schedule instructions accessing memory before this point.
+
+(define_expand "frame_blockage"
+  [(set (match_dup 0)
+       (unspec:BLK [(match_dup 1)] UNSPEC_FRAME_BLOCKAGE))]
+  ""
+{
+  operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
+  MEM_VOLATILE_P (operands[0]) = 1;
+  operands[1] = stack_pointer_rtx;
+})
+
+(define_insn "*frame_blockage<P:mode>"
+  [(set (match_operand:BLK 0 "" "")
+       (unspec:BLK [(match_operand:P 1 "" "")] UNSPEC_FRAME_BLOCKAGE))]
+  ""
+  ""
+  [(set_attr "length" "0")])
+
 (define_expand "probe_stack"
   [(set (match_operand 0 "memory_operand" "") (const_int 0))]
   ""