Commit ad89d820 by Max Filippov Committed by Max Filippov

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
parent aaec3d85
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> 2016-11-01 Jakub Jelinek <jakub@redhat.com>
* tree.h (BLOCK_IN_COLD_SECTION_P): Define. * tree.h (BLOCK_IN_COLD_SECTION_P): Define.
...@@ -68,6 +68,7 @@ extern rtx xtensa_return_addr (int, rtx); ...@@ -68,6 +68,7 @@ extern rtx xtensa_return_addr (int, rtx);
extern void xtensa_setup_frame_addresses (void); extern void xtensa_setup_frame_addresses (void);
extern int xtensa_dbx_register_number (int); extern int xtensa_dbx_register_number (int);
extern long compute_frame_size (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_prologue (void);
extern void xtensa_expand_epilogue (void); extern void xtensa_expand_epilogue (void);
extern void order_regs_for_local_alloc (void); extern void order_regs_for_local_alloc (void);
......
...@@ -79,11 +79,6 @@ enum internal_test ...@@ -79,11 +79,6 @@ enum internal_test
can support a given mode. */ can support a given mode. */
char xtensa_hard_regno_mode_ok[(int) MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER]; 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. */ /* Largest block move to handle in-line. */
#define LARGEST_MOVE_RATIO 15 #define LARGEST_MOVE_RATIO 15
...@@ -95,6 +90,13 @@ struct GTY(()) machine_function ...@@ -95,6 +90,13 @@ struct GTY(()) machine_function
bool vararg_a7; bool vararg_a7;
rtx vararg_a7_copy; rtx vararg_a7_copy;
rtx_insn *set_frame_ptr_insn; 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 /* Vector, indexed by hard register number, which contains 1 for a
...@@ -2632,24 +2634,29 @@ compute_frame_size (int size) ...@@ -2632,24 +2634,29 @@ compute_frame_size (int size)
{ {
int regno; int regno;
if (reload_completed && cfun->machine->frame_laid_out)
return cfun->machine->current_frame_size;
/* Add space for the incoming static chain value. */ /* Add space for the incoming static chain value. */
if (cfun->static_chain_decl != NULL) if (cfun->static_chain_decl != NULL)
size += (1 * UNITS_PER_WORD); size += (1 * UNITS_PER_WORD);
xtensa_callee_save_size = 0; cfun->machine->callee_save_size = 0;
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
{ {
if (xtensa_call_save_reg(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_STACK_ALIGN (size
+ xtensa_callee_save_size + cfun->machine->callee_save_size
+ crtl->outgoing_args_size + crtl->outgoing_args_size
+ (WINDOW_SIZE * UNITS_PER_WORD)); + (WINDOW_SIZE * UNITS_PER_WORD));
xtensa_callee_save_size = XTENSA_STACK_ALIGN (xtensa_callee_save_size); cfun->machine->callee_save_size =
return xtensa_current_frame_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) ...@@ -2703,6 +2710,7 @@ xtensa_expand_prologue (void)
{ {
int regno; int regno;
HOST_WIDE_INT offset = 0; HOST_WIDE_INT offset = 0;
int callee_save_size = cfun->machine->callee_save_size;
/* -128 is a limit of single addi instruction. */ /* -128 is a limit of single addi instruction. */
if (total_size > 0 && total_size <= 128) if (total_size > 0 && total_size <= 128)
...@@ -2716,7 +2724,7 @@ xtensa_expand_prologue (void) ...@@ -2716,7 +2724,7 @@ xtensa_expand_prologue (void)
add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx); add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx);
offset = total_size - UNITS_PER_WORD; 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 /* 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 * we move sp to the end of callee-saved save area, save and then
...@@ -2724,13 +2732,13 @@ xtensa_expand_prologue (void) ...@@ -2724,13 +2732,13 @@ xtensa_expand_prologue (void)
if (total_size > 1024) if (total_size > 1024)
{ {
insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, 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; RTX_FRAME_RELATED_P (insn) = 1;
note_rtx = gen_rtx_SET (stack_pointer_rtx, note_rtx = gen_rtx_SET (stack_pointer_rtx,
plus_constant (Pmode, 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); 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 else
{ {
...@@ -2766,13 +2774,13 @@ xtensa_expand_prologue (void) ...@@ -2766,13 +2774,13 @@ xtensa_expand_prologue (void)
{ {
rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG); rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG);
emit_move_insn (tmp_reg, GEN_INT (total_size - emit_move_insn (tmp_reg, GEN_INT (total_size -
xtensa_callee_save_size)); callee_save_size));
insn = emit_insn (gen_subsi3 (stack_pointer_rtx, insn = emit_insn (gen_subsi3 (stack_pointer_rtx,
stack_pointer_rtx, tmp_reg)); stack_pointer_rtx, tmp_reg));
RTX_FRAME_RELATED_P (insn) = 1; RTX_FRAME_RELATED_P (insn) = 1;
note_rtx = gen_rtx_SET (stack_pointer_rtx, note_rtx = gen_rtx_SET (stack_pointer_rtx,
plus_constant (Pmode, stack_pointer_rtx, plus_constant (Pmode, stack_pointer_rtx,
xtensa_callee_save_size - callee_save_size -
total_size)); total_size));
add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx); add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx);
} }
...@@ -2840,21 +2848,21 @@ xtensa_expand_epilogue (void) ...@@ -2840,21 +2848,21 @@ xtensa_expand_epilogue (void)
int regno; int regno;
HOST_WIDE_INT offset; 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); 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 -
xtensa_callee_save_size)); cfun->machine->callee_save_size));
emit_insn (gen_addsi3 (stack_pointer_rtx, frame_pointer_needed ? emit_insn (gen_addsi3 (stack_pointer_rtx, frame_pointer_needed ?
hard_frame_pointer_rtx : stack_pointer_rtx, hard_frame_pointer_rtx : stack_pointer_rtx,
tmp_reg)); tmp_reg));
offset = xtensa_callee_save_size - UNITS_PER_WORD; offset = cfun->machine->callee_save_size - UNITS_PER_WORD;
} }
else else
{ {
if (frame_pointer_needed) if (frame_pointer_needed)
emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx); 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 /* Prevent reordering of saved a0 update and loading it back from
...@@ -2874,16 +2882,16 @@ xtensa_expand_epilogue (void) ...@@ -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 */ if (frame_pointer_needed || /* always reachable with addi */
xtensa_current_frame_size > 1024 || cfun->machine->current_frame_size > 1024 ||
xtensa_current_frame_size <= 127) cfun->machine->current_frame_size <= 127)
{ {
if (xtensa_current_frame_size <= 127) if (cfun->machine->current_frame_size <= 127)
offset = xtensa_current_frame_size; offset = cfun->machine->current_frame_size;
else else
offset = xtensa_callee_save_size; offset = cfun->machine->callee_save_size;
emit_insn (gen_addsi3 (stack_pointer_rtx, emit_insn (gen_addsi3 (stack_pointer_rtx,
stack_pointer_rtx, stack_pointer_rtx,
...@@ -2892,7 +2900,8 @@ xtensa_expand_epilogue (void) ...@@ -2892,7 +2900,8 @@ xtensa_expand_epilogue (void)
else else
{ {
rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG); 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, emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
tmp_reg)); tmp_reg));
} }
...@@ -2903,11 +2912,22 @@ xtensa_expand_epilogue (void) ...@@ -2903,11 +2912,22 @@ xtensa_expand_epilogue (void)
stack_pointer_rtx, stack_pointer_rtx,
EH_RETURN_STACKADJ_RTX)); EH_RETURN_STACKADJ_RTX));
} }
xtensa_current_frame_size = 0; cfun->machine->epilogue_done = true;
xtensa_callee_save_size = 0;
emit_jump_insn (gen_return ()); 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 void
xtensa_set_return_address (rtx address, rtx scratch) xtensa_set_return_address (rtx address, rtx scratch)
{ {
......
...@@ -23,8 +23,6 @@ along with GCC; see the file COPYING3. If not see ...@@ -23,8 +23,6 @@ along with GCC; see the file COPYING3. If not see
/* External variables defined in xtensa.c. */ /* External variables defined in xtensa.c. */
extern unsigned xtensa_current_frame_size;
/* Macros used in the machine description to select various Xtensa /* Macros used in the machine description to select various Xtensa
configuration options. */ configuration options. */
#ifndef XCHAL_HAVE_MUL32_HIGH #ifndef XCHAL_HAVE_MUL32_HIGH
...@@ -477,14 +475,14 @@ enum reg_class ...@@ -477,14 +475,14 @@ enum reg_class
/* Specify the initial difference between the specified pair of registers. */ /* Specify the initial difference between the specified pair of registers. */
#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
do { \ do { \
compute_frame_size (get_frame_size ()); \ long frame_size = compute_frame_size (get_frame_size ()); \
switch (FROM) \ switch (FROM) \
{ \ { \
case FRAME_POINTER_REGNUM: \ case FRAME_POINTER_REGNUM: \
(OFFSET) = 0; \ (OFFSET) = 0; \
break; \ break; \
case ARG_POINTER_REGNUM: \ case ARG_POINTER_REGNUM: \
(OFFSET) = xtensa_current_frame_size; \ (OFFSET) = frame_size; \
break; \ break; \
default: \ default: \
gcc_unreachable (); \ gcc_unreachable (); \
......
...@@ -1663,7 +1663,7 @@ ...@@ -1663,7 +1663,7 @@
(define_insn "return" (define_insn "return"
[(return) [(return)
(use (reg:SI A0_REG))] (use (reg:SI A0_REG))]
"(TARGET_WINDOWED_ABI || !xtensa_current_frame_size) && reload_completed" "xtensa_use_return_instruction_p ()"
{ {
return TARGET_WINDOWED_ABI ? return TARGET_WINDOWED_ABI ?
(TARGET_DENSITY ? "retw.n" : "retw") : (TARGET_DENSITY ? "retw.n" : "retw") :
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment