|
@@ -0,0 +1,320 @@
|
|
|
|
+From 0d2556fa652cc85b3d042e862a38dd07d454175a Mon Sep 17 00:00:00 2001
|
|
|
|
+From: Max Filippov <jcmvbkbc@gmail.com>
|
|
|
|
+Date: Wed, 26 Oct 2016 08:02:51 +0000
|
|
|
|
+Subject: [PATCH 1/2] xtensa: Fix PR target/78118
|
|
|
|
+
|
|
|
|
+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-10-26 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.
|
|
|
|
+
|
|
|
|
+Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
|
|
|
|
+---
|
|
|
|
+Backported from: r241748
|
|
|
|
+
|
|
|
|
+ gcc/config/xtensa/xtensa-protos.h | 1 +
|
|
|
|
+ gcc/config/xtensa/xtensa.c | 82 ++++++++++++++++++++++++---------------
|
|
|
|
+ gcc/config/xtensa/xtensa.h | 6 +--
|
|
|
|
+ gcc/config/xtensa/xtensa.md | 2 +-
|
|
|
|
+ 4 files changed, 55 insertions(+), 36 deletions(-)
|
|
|
|
+
|
|
|
|
+diff --git a/gcc/config/xtensa/xtensa-protos.h b/gcc/config/xtensa/xtensa-protos.h
|
|
|
|
+index f2ca526..873557f 100644
|
|
|
|
+--- a/gcc/config/xtensa/xtensa-protos.h
|
|
|
|
++++ b/gcc/config/xtensa/xtensa-protos.h
|
|
|
|
+@@ -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);
|
|
|
|
+diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c
|
|
|
|
+index 64d089b..e49f784 100644
|
|
|
|
+--- a/gcc/config/xtensa/xtensa.c
|
|
|
|
++++ b/gcc/config/xtensa/xtensa.c
|
|
|
|
+@@ -78,11 +78,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
|
|
|
|
+
|
|
|
|
+@@ -94,6 +89,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
|
|
|
|
+@@ -2628,24 +2630,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;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+@@ -2696,6 +2703,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)
|
|
|
|
+@@ -2709,7 +2717,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
|
|
|
|
+@@ -2717,13 +2725,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
|
|
|
|
+ {
|
|
|
|
+@@ -2759,13 +2767,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);
|
|
|
|
+ }
|
|
|
|
+@@ -2833,21 +2841,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
|
|
|
|
+@@ -2867,16 +2875,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,
|
|
|
|
+@@ -2885,7 +2893,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));
|
|
|
|
+ }
|
|
|
|
+@@ -2896,11 +2905,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)
|
|
|
|
+ {
|
|
|
|
+diff --git a/gcc/config/xtensa/xtensa.h b/gcc/config/xtensa/xtensa.h
|
|
|
|
+index 82e9900..58eb1b2 100644
|
|
|
|
+--- a/gcc/config/xtensa/xtensa.h
|
|
|
|
++++ b/gcc/config/xtensa/xtensa.h
|
|
|
|
+@@ -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 (); \
|
|
|
|
+diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md
|
|
|
|
+index db54a12..fcdb6c8 100644
|
|
|
|
+--- a/gcc/config/xtensa/xtensa.md
|
|
|
|
++++ b/gcc/config/xtensa/xtensa.md
|
|
|
|
+@@ -1663,7 +1663,7 @@
|
|
|
|
+ (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") :
|
|
|
|
+--
|
|
|
|
+2.1.4
|
|
|
|
+
|