xtensa: Fix PR target/78118
authorMax Filippov <jcmvbkbc@gmail.com>
Tue, 1 Nov 2016 17:16:33 +0000 (17:16 +0000)
committerMax Filippov <jcmvbkbc@gcc.gnu.org>
Tue, 1 Nov 2016 17:16:33 +0000 (17:16 +0000)
It started failing after the following commit: 32e90dc6a0cda45 ("PR
rtl-optimization/61047").

The change that made xtensa backend go ICE looks completely unrelated,
and indeed, the issue is caused by the side effect of
compute_frame_size() function call hidden in the
INITIAL_ELIMINATION_OFFSET macro. This call updates the value of the
xtensa_current_frame_size static variable, used in "return" instruction
predicate. Prior to the change the value of xtensa_current_frame_size was
set to 0 after the end of epilogue generation, which enabled the "return"
instruction for the CALL0 ABI, but after the change the additional
INITIAL_ELIMINATION_OFFSET calls make xtensa_current_frame_size non-zero
and "return" pattern unavailable.

Get rid of the global xtensa_current_frame_size and
xtensa_callee_save_size variables by moving them into the
machine_function structure. Implement predicate for the "return" pattern
as a function. Don't communicate completion of epilogue generation
through zeroing of xtensa_current_frame_size, add explicit epilogue_done
variable to the machine_function structure. Don't update stack frame
layout after the completion of reload.

2016-11-01  Max Filippov  <jcmvbkbc@gmail.com>
gcc/
* config/xtensa/xtensa-protos.h
(xtensa_use_return_instruction_p): New prototype.
* config/xtensa/xtensa.c (xtensa_current_frame_size,
xtensa_callee_save_size): Remove.
(struct machine_function): Add new fields: current_frame_size,
callee_save_size, frame_laid_out and epilogue_done.
(compute_frame_size, xtensa_expand_prologue,
xtensa_expand_epilogue): Replace xtensa_callee_save_size with
cfun->machine->callee_save_size and xtensa_current_frame_size
with cfun->machine->current_frame_size.
(compute_frame_size): Update cfun->machine->frame_laid_out and
don't update frame layout after reload completion.
(xtensa_expand_epilogue): Set cfun->machine->epilogue_done
instead of zeroing xtensa_current_frame_size.
(xtensa_use_return_instruction_p): New function.
* config/xtensa/xtensa.h (xtensa_current_frame_size): Remove
declaration.
(INITIAL_ELIMINATION_OFFSET): Use return value of
compute_frame_size instead of xtensa_current_frame_size value.
* config/xtensa/xtensa.md ("return" pattern): Use new predicate
function xtensa_use_return_instruction_p instead of inline code.

From-SVN: r241748

gcc/ChangeLog
gcc/config/xtensa/xtensa-protos.h
gcc/config/xtensa/xtensa.c
gcc/config/xtensa/xtensa.h
gcc/config/xtensa/xtensa.md

index e5ae00a..7d4fd69 100644 (file)
@@ -1,3 +1,27 @@
+2016-11-01  Max Filippov  <jcmvbkbc@gmail.com>
+
+       * config/xtensa/xtensa-protos.h
+       (xtensa_use_return_instruction_p): New prototype.
+       * config/xtensa/xtensa.c (xtensa_current_frame_size,
+       xtensa_callee_save_size): Remove.
+       (struct machine_function): Add new fields: current_frame_size,
+       callee_save_size, frame_laid_out and epilogue_done.
+       (compute_frame_size, xtensa_expand_prologue,
+       xtensa_expand_epilogue): Replace xtensa_callee_save_size with
+       cfun->machine->callee_save_size and xtensa_current_frame_size
+       with cfun->machine->current_frame_size.
+       (compute_frame_size): Update cfun->machine->frame_laid_out and
+       don't update frame layout after reload completion.
+       (xtensa_expand_epilogue): Set cfun->machine->epilogue_done
+       instead of zeroing xtensa_current_frame_size.
+       (xtensa_use_return_instruction_p): New function.
+       * config/xtensa/xtensa.h (xtensa_current_frame_size): Remove
+       declaration.
+       (INITIAL_ELIMINATION_OFFSET): Use return value of
+       compute_frame_size instead of xtensa_current_frame_size value.
+       * config/xtensa/xtensa.md ("return" pattern): Use new predicate
+       function xtensa_use_return_instruction_p instead of inline code.
+
 2016-11-01  Jakub Jelinek  <jakub@redhat.com>
 
        * tree.h (BLOCK_IN_COLD_SECTION_P): Define.
index f2ca526..873557f 100644 (file)
@@ -68,6 +68,7 @@ extern rtx xtensa_return_addr (int, rtx);
 extern void xtensa_setup_frame_addresses (void);
 extern int xtensa_dbx_register_number (int);
 extern long compute_frame_size (int);
+extern bool xtensa_use_return_instruction_p (void);
 extern void xtensa_expand_prologue (void);
 extern void xtensa_expand_epilogue (void);
 extern void order_regs_for_local_alloc (void);
index 60e5029..2115b57 100644 (file)
@@ -79,11 +79,6 @@ enum internal_test
    can support a given mode.  */
 char xtensa_hard_regno_mode_ok[(int) MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER];
 
-/* Current frame size calculated by compute_frame_size.  */
-unsigned xtensa_current_frame_size;
-/* Callee-save area size in the current frame calculated by compute_frame_size. */
-int xtensa_callee_save_size;
-
 /* Largest block move to handle in-line.  */
 #define LARGEST_MOVE_RATIO 15
 
@@ -95,6 +90,13 @@ struct GTY(()) machine_function
   bool vararg_a7;
   rtx vararg_a7_copy;
   rtx_insn *set_frame_ptr_insn;
+  /* Current frame size calculated by compute_frame_size.  */
+  unsigned current_frame_size;
+  /* Callee-save area size in the current frame calculated by
+     compute_frame_size.  */
+  int callee_save_size;
+  bool frame_laid_out;
+  bool epilogue_done;
 };
 
 /* Vector, indexed by hard register number, which contains 1 for a
@@ -2632,24 +2634,29 @@ compute_frame_size (int size)
 {
   int regno;
 
+  if (reload_completed && cfun->machine->frame_laid_out)
+    return cfun->machine->current_frame_size;
+
   /* Add space for the incoming static chain value.  */
   if (cfun->static_chain_decl != NULL)
     size += (1 * UNITS_PER_WORD);
 
-  xtensa_callee_save_size = 0;
+  cfun->machine->callee_save_size = 0;
   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
     {
       if (xtensa_call_save_reg(regno))
-       xtensa_callee_save_size += UNITS_PER_WORD;
+       cfun->machine->callee_save_size += UNITS_PER_WORD;
     }
 
-  xtensa_current_frame_size =
+  cfun->machine->current_frame_size =
     XTENSA_STACK_ALIGN (size
-                       + xtensa_callee_save_size
+                       + cfun->machine->callee_save_size
                        + crtl->outgoing_args_size
                        + (WINDOW_SIZE * UNITS_PER_WORD));
-  xtensa_callee_save_size = XTENSA_STACK_ALIGN (xtensa_callee_save_size);
-  return xtensa_current_frame_size;
+  cfun->machine->callee_save_size =
+    XTENSA_STACK_ALIGN (cfun->machine->callee_save_size);
+  cfun->machine->frame_laid_out = true;
+  return cfun->machine->current_frame_size;
 }
 
 
@@ -2703,6 +2710,7 @@ xtensa_expand_prologue (void)
     {
       int regno;
       HOST_WIDE_INT offset = 0;
+      int callee_save_size = cfun->machine->callee_save_size;
 
       /* -128 is a limit of single addi instruction. */
       if (total_size > 0 && total_size <= 128)
@@ -2716,7 +2724,7 @@ xtensa_expand_prologue (void)
          add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx);
          offset = total_size - UNITS_PER_WORD;
        }
-      else if (xtensa_callee_save_size)
+      else if (callee_save_size)
        {
          /* 1020 is maximal s32i offset, if the frame is bigger than that
           * we move sp to the end of callee-saved save area, save and then
@@ -2724,13 +2732,13 @@ xtensa_expand_prologue (void)
          if (total_size > 1024)
            {
              insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
-                                           GEN_INT (-xtensa_callee_save_size)));
+                                           GEN_INT (-callee_save_size)));
              RTX_FRAME_RELATED_P (insn) = 1;
              note_rtx = gen_rtx_SET (stack_pointer_rtx,
                                      plus_constant (Pmode, stack_pointer_rtx,
-                                                    -xtensa_callee_save_size));
+                                                    -callee_save_size));
              add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx);
-             offset = xtensa_callee_save_size - UNITS_PER_WORD;
+             offset = callee_save_size - UNITS_PER_WORD;
            }
          else
            {
@@ -2766,13 +2774,13 @@ xtensa_expand_prologue (void)
        {
          rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG);
          emit_move_insn (tmp_reg, GEN_INT (total_size -
-                                           xtensa_callee_save_size));
+                                           callee_save_size));
          insn = emit_insn (gen_subsi3 (stack_pointer_rtx,
                                        stack_pointer_rtx, tmp_reg));
          RTX_FRAME_RELATED_P (insn) = 1;
          note_rtx = gen_rtx_SET (stack_pointer_rtx,
                                  plus_constant (Pmode, stack_pointer_rtx,
-                                                xtensa_callee_save_size -
+                                                callee_save_size -
                                                 total_size));
          add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx);
        }
@@ -2840,21 +2848,21 @@ xtensa_expand_epilogue (void)
       int regno;
       HOST_WIDE_INT offset;
 
-      if (xtensa_current_frame_size > (frame_pointer_needed ? 127 : 1024))
+      if (cfun->machine->current_frame_size > (frame_pointer_needed ? 127 : 1024))
        {
          rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG);
-         emit_move_insn (tmp_reg, GEN_INT (xtensa_current_frame_size -
-                                           xtensa_callee_save_size));
+         emit_move_insn (tmp_reg, GEN_INT (cfun->machine->current_frame_size -
+                                           cfun->machine->callee_save_size));
          emit_insn (gen_addsi3 (stack_pointer_rtx, frame_pointer_needed ?
                                 hard_frame_pointer_rtx : stack_pointer_rtx,
                                 tmp_reg));
-         offset = xtensa_callee_save_size - UNITS_PER_WORD;
+         offset = cfun->machine->callee_save_size - UNITS_PER_WORD;
        }
       else
        {
          if (frame_pointer_needed)
            emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx);
-         offset = xtensa_current_frame_size - UNITS_PER_WORD;
+         offset = cfun->machine->current_frame_size - UNITS_PER_WORD;
        }
 
       /* Prevent reordering of saved a0 update and loading it back from
@@ -2874,16 +2882,16 @@ xtensa_expand_epilogue (void)
            }
        }
 
-      if (xtensa_current_frame_size > 0)
+      if (cfun->machine->current_frame_size > 0)
        {
          if (frame_pointer_needed || /* always reachable with addi */
-             xtensa_current_frame_size > 1024 ||
-             xtensa_current_frame_size <= 127)
+             cfun->machine->current_frame_size > 1024 ||
+             cfun->machine->current_frame_size <= 127)
            {
-             if (xtensa_current_frame_size <= 127)
-               offset = xtensa_current_frame_size;
+             if (cfun->machine->current_frame_size <= 127)
+               offset = cfun->machine->current_frame_size;
              else
-               offset = xtensa_callee_save_size;
+               offset = cfun->machine->callee_save_size;
 
              emit_insn (gen_addsi3 (stack_pointer_rtx,
                                     stack_pointer_rtx,
@@ -2892,7 +2900,8 @@ xtensa_expand_epilogue (void)
          else
            {
              rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG);
-             emit_move_insn (tmp_reg, GEN_INT (xtensa_current_frame_size));
+             emit_move_insn (tmp_reg,
+                             GEN_INT (cfun->machine->current_frame_size));
              emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
                                     tmp_reg));
            }
@@ -2903,11 +2912,22 @@ xtensa_expand_epilogue (void)
                                  stack_pointer_rtx,
                                  EH_RETURN_STACKADJ_RTX));
     }
-  xtensa_current_frame_size = 0;
-  xtensa_callee_save_size = 0;
+  cfun->machine->epilogue_done = true;
   emit_jump_insn (gen_return ());
 }
 
+bool
+xtensa_use_return_instruction_p (void)
+{
+  if (!reload_completed)
+    return false;
+  if (TARGET_WINDOWED_ABI)
+    return true;
+  if (compute_frame_size (get_frame_size ()) == 0)
+    return true;
+  return cfun->machine->epilogue_done;
+}
+
 void
 xtensa_set_return_address (rtx address, rtx scratch)
 {
index 82e9900..58eb1b2 100644 (file)
@@ -23,8 +23,6 @@ along with GCC; see the file COPYING3.  If not see
 
 /* External variables defined in xtensa.c.  */
 
-extern unsigned xtensa_current_frame_size;
-
 /* Macros used in the machine description to select various Xtensa
    configuration options.  */
 #ifndef XCHAL_HAVE_MUL32_HIGH
@@ -477,14 +475,14 @@ enum reg_class
 /* Specify the initial difference between the specified pair of registers.  */
 #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)                   \
   do {                                                                 \
-    compute_frame_size (get_frame_size ());                            \
+    long frame_size = compute_frame_size (get_frame_size ());          \
     switch (FROM)                                                      \
       {                                                                        \
       case FRAME_POINTER_REGNUM:                                       \
         (OFFSET) = 0;                                                  \
        break;                                                          \
       case ARG_POINTER_REGNUM:                                         \
-        (OFFSET) = xtensa_current_frame_size;                          \
+        (OFFSET) = frame_size;                                         \
        break;                                                          \
       default:                                                         \
        gcc_unreachable ();                                             \
index db54a12..fcdb6c8 100644 (file)
 (define_insn "return"
   [(return)
    (use (reg:SI A0_REG))]
-  "(TARGET_WINDOWED_ABI || !xtensa_current_frame_size) && reload_completed"
+  "xtensa_use_return_instruction_p ()"
 {
   return TARGET_WINDOWED_ABI ?
       (TARGET_DENSITY ? "retw.n" : "retw") :