]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
xtensa: fix PR target/65416
authorMax Filippov <jcmvbkbc@gmail.com>
Tue, 19 Jun 2018 21:01:22 +0000 (21:01 +0000)
committerMax Filippov <jcmvbkbc@gcc.gnu.org>
Tue, 19 Jun 2018 21:01:22 +0000 (21:01 +0000)
The issue is caused by reordering of stack pointer update after stack
space allocation with instructions that write to the allocated stack
space. In windowed ABI register spill area for the previous call frame
is located just below the stack pointer and may be reloaded back into
the register file on movsp.
Implement allocate_stack pattern for windowed ABI configuration and
insert an instruction that prevents reordering of frame memory access
and stack pointer update.

gcc/
2018-06-19  Max Filippov  <jcmvbkbc@gmail.com>

Backport from mainline
2018-06-19  Max Filippov  <jcmvbkbc@gmail.com>

* config/xtensa/xtensa.md (UNSPEC_FRAME_BLOCKAGE): New unspec
constant.
(allocate_stack, frame_blockage, *frame_blockage): New patterns.

From-SVN: r261764

gcc/ChangeLog
gcc/config/xtensa/xtensa.md

index a3fee2c7d7dc2ddf83a6f62fd375d5fb22ac70dd..4d4d9a02a9a5042a0cda536237e4826ca87b34ac 100644 (file)
@@ -1,3 +1,12 @@
+2018-06-19  Max Filippov  <jcmvbkbc@gmail.com>
+
+       Backport from mainline
+       2018-06-19  Max Filippov  <jcmvbkbc@gmail.com>
+
+       * config/xtensa/xtensa.md (UNSPEC_FRAME_BLOCKAGE): New unspec
+       constant.
+       (allocate_stack, frame_blockage, *frame_blockage): New patterns.
+
 2018-06-19  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gimplify.c (gimplify_init_constructor): Really never clear for an
index d5596e25d8287d0c140c5b4e3f5ee555d85ba483..0eba10b742cd85af0476dec5d638d620d91968c8 100644 (file)
@@ -38,6 +38,7 @@
   (UNSPEC_MEMW         11)
   (UNSPEC_LSETUP_START  12)
   (UNSPEC_LSETUP_END    13)
+  (UNSPEC_FRAME_BLOCKAGE 14)
 
   (UNSPECV_SET_FP      1)
   (UNSPECV_ENTRY       2)
 \f
 ;; Miscellaneous instructions.
 
+;; In windowed ABI stack pointer adjustment must happen before any access
+;; to the space allocated on stack is allowed, otherwise register spill
+;; area may be clobbered.  That's what frame blockage is supposed to enforce.
+
+(define_expand "allocate_stack"
+  [(set (match_operand 0 "nonimmed_operand")
+        (minus (reg A1_REG) (match_operand 1 "add_operand")))
+   (set (reg A1_REG)
+        (minus (reg A1_REG) (match_dup 1)))]
+  "TARGET_WINDOWED_ABI"
+{
+  if (CONST_INT_P (operands[1]))
+    {
+      rtx neg_op0 = GEN_INT (-INTVAL (operands[1]));
+      emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, neg_op0));
+    }
+  else
+    {
+      emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
+                            operands[1]));
+    }
+  emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
+  emit_insn (gen_frame_blockage ());
+  DONE;
+})
+
 (define_expand "prologue"
   [(const_int 0)]
   ""
   [(set_attr "length" "0")
    (set_attr "type" "nop")])
 
+;; 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"
+  [(set (match_operand:BLK 0 "" "")
+        (unspec:BLK [(match_operand:SI 1 "" "")] UNSPEC_FRAME_BLOCKAGE))]
+  ""
+  ""
+  [(set_attr "length" "0")])
+
 (define_insn "trap"
   [(trap_if (const_int 1) (const_int 0))]
   ""