aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2016-11-01 17:16:33 +0000
committerMax Filippov <jcmvbkbc@gcc.gnu.org>2016-11-01 17:16:33 +0000
commitad89d820bf04a06b636fe7ecd37e4e6e4a1942d5 (patch)
treebcd7af4c2659c69e60e6ea832ebe225bf5664f49
parentaaec3d850a73cd951ccec98f2f55d62832ca2ee2 (diff)
downloadgcc-ad89d820bf04a06b636fe7ecd37e4e6e4a1942d5.zip
gcc-ad89d820bf04a06b636fe7ecd37e4e6e4a1942d5.tar.gz
gcc-ad89d820bf04a06b636fe7ecd37e4e6e4a1942d5.tar.bz2
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-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
-rw-r--r--gcc/ChangeLog24
-rw-r--r--gcc/config/xtensa/xtensa-protos.h1
-rw-r--r--gcc/config/xtensa/xtensa.c82
-rw-r--r--gcc/config/xtensa/xtensa.h6
-rw-r--r--gcc/config/xtensa/xtensa.md2
5 files changed, 79 insertions, 36 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e5ae00a..7d4fd69 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
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 60e5029..2115b57 100644
--- a/gcc/config/xtensa/xtensa.c
+++ b/gcc/config/xtensa/xtensa.c
@@ -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)
{
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") :