re PR other/50925 ([avr] ICE at spill_failure, at reload1.c:2118)
PR target/50925 * config/avr/avr-protos.h (avr_hard_regno_nregs): Declare. * config/avr/avr.c (avr_can_eliminate): Simplify. (avr_initial_elimination_offset): Likewise. (avr_prologue_setup_frame): Use hard_frame_pointer_rtx. (expand_epilogue): Likewise. (avr_legitimize_address): Gut. (avr_legitimize_reload_address): Use hard_frame_pointer_rtx. (avr_hard_regno_nregs): New. (avr_hard_regno_ok): Allow only Pmode for arg and frame_pointers. (avr_regno_mode_code_ok_for_base_b): Handle arg and frame pointers. * config/avr/avr.h (FIXED_REGISTERS): Adjust arg pointer, add soft frame pointer. (CALL_USED_REGISTERS): Likewise. (REG_CLASS_CONTENTS): Likewise. (REGISTER_NAMES): Likewise. (HARD_REGNO_NREGS): Use avr_hard_regno_nregs. (HARD_FRAME_POINTER_REGNUM): New. (FRAME_POINTER_REGNUM): Use soft frame pointer. (ELIMINABLE_REGS): Eliminate from the soft frame pointer, remove the HARD_FRAME_POINTER self-elimination. Co-Authored-By: Denis Chertykov <chertykov@gmail.com> From-SVN: r183136
This commit is contained in:
parent
4643a68ec2
commit
105b876e55
@ -1,3 +1,28 @@
|
||||
2012-01-09 Richard Henderson <rth@redhat.com>
|
||||
Denis Chertykov <chertykov@gmail.com>
|
||||
|
||||
PR target/50925
|
||||
* config/avr/avr-protos.h (avr_hard_regno_nregs): Declare.
|
||||
* config/avr/avr.c (avr_can_eliminate): Simplify.
|
||||
(avr_initial_elimination_offset): Likewise.
|
||||
(avr_prologue_setup_frame): Use hard_frame_pointer_rtx.
|
||||
(expand_epilogue): Likewise.
|
||||
(avr_legitimize_address): Gut.
|
||||
(avr_legitimize_reload_address): Use hard_frame_pointer_rtx.
|
||||
(avr_hard_regno_nregs): New.
|
||||
(avr_hard_regno_ok): Allow only Pmode for arg and frame_pointers.
|
||||
(avr_regno_mode_code_ok_for_base_b): Handle arg and frame pointers.
|
||||
* config/avr/avr.h (FIXED_REGISTERS): Adjust arg pointer,
|
||||
add soft frame pointer.
|
||||
(CALL_USED_REGISTERS): Likewise.
|
||||
(REG_CLASS_CONTENTS): Likewise.
|
||||
(REGISTER_NAMES): Likewise.
|
||||
(HARD_REGNO_NREGS): Use avr_hard_regno_nregs.
|
||||
(HARD_FRAME_POINTER_REGNUM): New.
|
||||
(FRAME_POINTER_REGNUM): Use soft frame pointer.
|
||||
(ELIMINABLE_REGS): Eliminate from the soft frame pointer,
|
||||
remove the HARD_FRAME_POINTER self-elimination.
|
||||
|
||||
2012-01-12 Georg-Johann Lay <avr@gjlay.de>
|
||||
|
||||
PR target/51756
|
||||
|
@ -109,6 +109,7 @@ extern int avr_jump_mode (rtx x, rtx insn);
|
||||
extern int test_hard_reg_class (enum reg_class rclass, rtx x);
|
||||
extern int jump_over_one_insn_p (rtx insn, rtx dest);
|
||||
|
||||
extern int avr_hard_regno_nregs (int regno, enum machine_mode mode);
|
||||
extern int avr_hard_regno_mode_ok (int regno, enum machine_mode mode);
|
||||
extern void final_prescan_insn (rtx insn, rtx *operand, int num_operands);
|
||||
extern int avr_simplify_comparison_p (enum machine_mode mode,
|
||||
|
@ -686,31 +686,28 @@ avr_regs_to_save (HARD_REG_SET *set)
|
||||
/* Return true if register FROM can be eliminated via register TO. */
|
||||
|
||||
static bool
|
||||
avr_can_eliminate (const int from, const int to)
|
||||
avr_can_eliminate (int from ATTRIBUTE_UNUSED, int to)
|
||||
{
|
||||
return ((from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
|
||||
|| (frame_pointer_needed && to == FRAME_POINTER_REGNUM)
|
||||
|| ((from == FRAME_POINTER_REGNUM
|
||||
|| from == FRAME_POINTER_REGNUM + 1)
|
||||
&& !frame_pointer_needed));
|
||||
return to == HARD_FRAME_POINTER_REGNUM;
|
||||
}
|
||||
|
||||
/* Compute offset between arg_pointer and frame_pointer. */
|
||||
|
||||
int
|
||||
avr_initial_elimination_offset (int from, int to)
|
||||
avr_initial_elimination_offset (int from, int to ATTRIBUTE_UNUSED)
|
||||
{
|
||||
if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
|
||||
return 0;
|
||||
else
|
||||
int offset = 0;
|
||||
|
||||
if (from == ARG_POINTER_REGNUM)
|
||||
{
|
||||
int offset = frame_pointer_needed ? 2 : 0;
|
||||
int avr_pc_size = AVR_HAVE_EIJMP_EICALL ? 3 : 2;
|
||||
|
||||
offset += AVR_HAVE_EIJMP_EICALL ? 3 : 2;
|
||||
offset += frame_pointer_needed ? 2 : 0;
|
||||
offset += avr_regs_to_save (NULL);
|
||||
return (get_frame_size () + avr_outgoing_args_size()
|
||||
+ avr_pc_size + 1 + offset);
|
||||
offset += get_frame_size ();
|
||||
offset += 1; /* post-dec stack space */
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
/* Actual start of frame is virtual_stack_vars_rtx this is offset from
|
||||
@ -902,12 +899,12 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set)
|
||||
notes to the front. Thus we build them in the reverse order of
|
||||
how we want dwarf2out to process them. */
|
||||
|
||||
/* The function does always set frame_pointer_rtx, but whether that
|
||||
/* The function does always set hard_frame_pointer_rtx, but whether that
|
||||
is going to be permanent in the function is frame_pointer_needed. */
|
||||
|
||||
add_reg_note (insn, REG_CFA_ADJUST_CFA,
|
||||
gen_rtx_SET (VOIDmode, (frame_pointer_needed
|
||||
? frame_pointer_rtx
|
||||
? hard_frame_pointer_rtx
|
||||
: stack_pointer_rtx),
|
||||
plus_constant (stack_pointer_rtx,
|
||||
-(size + live_seq))));
|
||||
@ -952,7 +949,7 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set)
|
||||
if (frame_pointer_needed
|
||||
&& size == 0)
|
||||
{
|
||||
insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
|
||||
insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
|
||||
@ -987,7 +984,7 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set)
|
||||
|| !current_function_is_leaf);
|
||||
|
||||
fp = my_fp = (frame_pointer_needed
|
||||
? frame_pointer_rtx
|
||||
? hard_frame_pointer_rtx
|
||||
: gen_rtx_REG (Pmode, REG_X));
|
||||
|
||||
if (AVR_HAVE_8BIT_SP)
|
||||
@ -995,7 +992,7 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set)
|
||||
/* The high byte (r29) does not change:
|
||||
Prefer SUBI (1 cycle) over ABIW (2 cycles, same size). */
|
||||
|
||||
my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
|
||||
my_fp = all_regs_rtx[HARD_FRAME_POINTER_REGNUM];
|
||||
}
|
||||
|
||||
/************ Method 1: Adjust frame pointer ************/
|
||||
@ -1260,13 +1257,13 @@ expand_epilogue (bool sibcall_p)
|
||||
|
||||
if (!frame_pointer_needed)
|
||||
{
|
||||
emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
|
||||
emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
|
||||
}
|
||||
|
||||
if (size)
|
||||
{
|
||||
emit_move_insn (frame_pointer_rtx,
|
||||
plus_constant (frame_pointer_rtx, size));
|
||||
emit_move_insn (hard_frame_pointer_rtx,
|
||||
plus_constant (hard_frame_pointer_rtx, size));
|
||||
}
|
||||
|
||||
emit_insn (gen_epilogue_restores (gen_int_mode (live_seq, HImode)));
|
||||
@ -1285,7 +1282,7 @@ expand_epilogue (bool sibcall_p)
|
||||
|| !current_function_is_leaf);
|
||||
|
||||
fp = my_fp = (frame_pointer_needed
|
||||
? frame_pointer_rtx
|
||||
? hard_frame_pointer_rtx
|
||||
: gen_rtx_REG (Pmode, REG_X));
|
||||
|
||||
if (AVR_HAVE_8BIT_SP)
|
||||
@ -1293,7 +1290,7 @@ expand_epilogue (bool sibcall_p)
|
||||
/* The high byte (r29) does not change:
|
||||
Prefer SUBI (1 cycle) over SBIW (2 cycles). */
|
||||
|
||||
my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
|
||||
my_fp = all_regs_rtx[HARD_FRAME_POINTER_REGNUM];
|
||||
}
|
||||
|
||||
/********** Method 1: Adjust fp register **********/
|
||||
@ -1534,37 +1531,8 @@ avr_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
|
||||
memory address for an operand of mode MODE */
|
||||
|
||||
static rtx
|
||||
avr_legitimize_address (rtx x, rtx oldx, enum machine_mode mode)
|
||||
avr_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, enum machine_mode mode)
|
||||
{
|
||||
bool big_offset_p = false;
|
||||
|
||||
x = oldx;
|
||||
|
||||
if (GET_CODE (oldx) == PLUS
|
||||
&& REG_P (XEXP (oldx, 0)))
|
||||
{
|
||||
if (REG_P (XEXP (oldx, 1)))
|
||||
x = force_reg (GET_MODE (oldx), oldx);
|
||||
else if (CONST_INT_P (XEXP (oldx, 1)))
|
||||
{
|
||||
int offs = INTVAL (XEXP (oldx, 1));
|
||||
if (frame_pointer_rtx != XEXP (oldx, 0)
|
||||
&& offs > MAX_LD_OFFSET (mode))
|
||||
{
|
||||
big_offset_p = true;
|
||||
x = force_reg (GET_MODE (oldx), oldx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (avr_log.legitimize_address)
|
||||
{
|
||||
avr_edump ("\n%?: mode=%m\n %r\n", mode, oldx);
|
||||
|
||||
if (x != oldx)
|
||||
avr_edump (" %s --> %r\n", big_offset_p ? "(big offset)" : "", x);
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
@ -1634,7 +1602,7 @@ avr_legitimize_reload_address (rtx *px, enum machine_mode mode,
|
||||
}
|
||||
}
|
||||
else if (! (frame_pointer_needed
|
||||
&& XEXP (x, 0) == frame_pointer_rtx))
|
||||
&& XEXP (x, 0) == hard_frame_pointer_rtx))
|
||||
{
|
||||
push_reload (x, NULL_RTX, px, NULL,
|
||||
POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
|
||||
@ -8366,6 +8334,19 @@ extra_constraint_Q (rtx x)
|
||||
return ok;
|
||||
}
|
||||
|
||||
/* Returns the number of registers required to hold a value of MODE. */
|
||||
|
||||
int
|
||||
avr_hard_regno_nregs (int regno, enum machine_mode mode)
|
||||
{
|
||||
/* The fake registers are designed to hold exactly a pointer. */
|
||||
if (regno == ARG_POINTER_REGNUM || regno == FRAME_POINTER_REGNUM)
|
||||
return 1;
|
||||
|
||||
return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
|
||||
}
|
||||
|
||||
|
||||
/* Convert condition code CONDITION to the valid AVR condition code. */
|
||||
|
||||
RTX_CODE
|
||||
@ -8789,6 +8770,10 @@ jump_over_one_insn_p (rtx insn, rtx dest)
|
||||
int
|
||||
avr_hard_regno_mode_ok (int regno, enum machine_mode mode)
|
||||
{
|
||||
/* The fake registers are designed to hold exactly a pointer. */
|
||||
if (regno == ARG_POINTER_REGNUM || regno == FRAME_POINTER_REGNUM)
|
||||
return mode == Pmode;
|
||||
|
||||
/* NOTE: 8-bit values must not be disallowed for R28 or R29.
|
||||
Disallowing QI et al. in these regs might lead to code like
|
||||
(set (subreg:QI (reg:HI 28) n) ...)
|
||||
@ -8812,7 +8797,6 @@ avr_hard_regno_mode_ok (int regno, enum machine_mode mode)
|
||||
return 0;
|
||||
|
||||
/* All modes larger than 8 bits should start in an even register. */
|
||||
|
||||
return !(regno & 1);
|
||||
}
|
||||
|
||||
@ -8872,7 +8856,8 @@ avr_regno_mode_code_ok_for_base_p (int regno,
|
||||
&& (regno == REG_X
|
||||
|| regno == REG_Y
|
||||
|| regno == REG_Z
|
||||
|| regno == ARG_POINTER_REGNUM))
|
||||
|| regno == ARG_POINTER_REGNUM
|
||||
|| regno == FRAME_POINTER_REGNUM))
|
||||
{
|
||||
ok = true;
|
||||
}
|
||||
@ -8883,7 +8868,8 @@ avr_regno_mode_code_ok_for_base_p (int regno,
|
||||
if (regno == REG_X
|
||||
|| regno == REG_Y
|
||||
|| regno == REG_Z
|
||||
|| regno == ARG_POINTER_REGNUM)
|
||||
|| regno == ARG_POINTER_REGNUM
|
||||
|| regno == FRAME_POINTER_REGNUM)
|
||||
{
|
||||
ok = true;
|
||||
}
|
||||
|
@ -231,45 +231,47 @@ enum
|
||||
|
||||
#define FIRST_PSEUDO_REGISTER 36
|
||||
|
||||
#define FIXED_REGISTERS {\
|
||||
1,1,/* r0 r1 */\
|
||||
0,0,/* r2 r3 */\
|
||||
0,0,/* r4 r5 */\
|
||||
0,0,/* r6 r7 */\
|
||||
0,0,/* r8 r9 */\
|
||||
0,0,/* r10 r11 */\
|
||||
0,0,/* r12 r13 */\
|
||||
0,0,/* r14 r15 */\
|
||||
0,0,/* r16 r17 */\
|
||||
0,0,/* r18 r19 */\
|
||||
0,0,/* r20 r21 */\
|
||||
0,0,/* r22 r23 */\
|
||||
0,0,/* r24 r25 */\
|
||||
0,0,/* r26 r27 */\
|
||||
0,0,/* r28 r29 */\
|
||||
0,0,/* r30 r31 */\
|
||||
1,1,/* STACK */\
|
||||
1,1 /* arg pointer */ }
|
||||
#define FIXED_REGISTERS { \
|
||||
1,1,/* r0 r1 */ \
|
||||
0,0,/* r2 r3 */ \
|
||||
0,0,/* r4 r5 */ \
|
||||
0,0,/* r6 r7 */ \
|
||||
0,0,/* r8 r9 */ \
|
||||
0,0,/* r10 r11 */ \
|
||||
0,0,/* r12 r13 */ \
|
||||
0,0,/* r14 r15 */ \
|
||||
0,0,/* r16 r17 */ \
|
||||
0,0,/* r18 r19 */ \
|
||||
0,0,/* r20 r21 */ \
|
||||
0,0,/* r22 r23 */ \
|
||||
0,0,/* r24 r25 */ \
|
||||
0,0,/* r26 r27 */ \
|
||||
0,0,/* r28 r29 */ \
|
||||
0,0,/* r30 r31 */ \
|
||||
1,1,/* STACK */ \
|
||||
1, /* arg pointer */ \
|
||||
1 /* frame pointer */ }
|
||||
|
||||
#define CALL_USED_REGISTERS { \
|
||||
1,1,/* r0 r1 */ \
|
||||
0,0,/* r2 r3 */ \
|
||||
0,0,/* r4 r5 */ \
|
||||
0,0,/* r6 r7 */ \
|
||||
0,0,/* r8 r9 */ \
|
||||
0,0,/* r10 r11 */ \
|
||||
0,0,/* r12 r13 */ \
|
||||
0,0,/* r14 r15 */ \
|
||||
0,0,/* r16 r17 */ \
|
||||
1,1,/* r18 r19 */ \
|
||||
1,1,/* r20 r21 */ \
|
||||
1,1,/* r22 r23 */ \
|
||||
1,1,/* r24 r25 */ \
|
||||
1,1,/* r26 r27 */ \
|
||||
0,0,/* r28 r29 */ \
|
||||
1,1,/* r30 r31 */ \
|
||||
1,1,/* STACK */ \
|
||||
1,1 /* arg pointer */ }
|
||||
0,0,/* r2 r3 */ \
|
||||
0,0,/* r4 r5 */ \
|
||||
0,0,/* r6 r7 */ \
|
||||
0,0,/* r8 r9 */ \
|
||||
0,0,/* r10 r11 */ \
|
||||
0,0,/* r12 r13 */ \
|
||||
0,0,/* r14 r15 */ \
|
||||
0,0,/* r16 r17 */ \
|
||||
1,1,/* r18 r19 */ \
|
||||
1,1,/* r20 r21 */ \
|
||||
1,1,/* r22 r23 */ \
|
||||
1,1,/* r24 r25 */ \
|
||||
1,1,/* r26 r27 */ \
|
||||
0,0,/* r28 r29 */ \
|
||||
1,1,/* r30 r31 */ \
|
||||
1,1,/* STACK */ \
|
||||
1, /* arg pointer */ \
|
||||
1 /* frame pointer */ }
|
||||
|
||||
#define REG_ALLOC_ORDER { \
|
||||
24,25, \
|
||||
@ -287,7 +289,7 @@ enum
|
||||
#define ADJUST_REG_ALLOC_ORDER order_regs_for_local_alloc ()
|
||||
|
||||
|
||||
#define HARD_REGNO_NREGS(REGNO, MODE) ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
|
||||
#define HARD_REGNO_NREGS(REGNO, MODE) avr_hard_regno_nregs(REGNO, MODE)
|
||||
|
||||
#define HARD_REGNO_MODE_OK(REGNO, MODE) avr_hard_regno_mode_ok(REGNO, MODE)
|
||||
|
||||
@ -337,17 +339,17 @@ enum reg_class {
|
||||
{3 << REG_Z,0x00000000}, /* POINTER_Z_REGS, r30 - r31 */ \
|
||||
{0x00000000,0x00000003}, /* STACK_REG, STACK */ \
|
||||
{(3 << REG_Y) | (3 << REG_Z), \
|
||||
0x00000000}, /* BASE_POINTER_REGS, r28 - r31 */ \
|
||||
0x0000000c}, /* BASE_POINTER_REGS, r28 - r31,ap,fp */ \
|
||||
{(3 << REG_X) | (3 << REG_Y) | (3 << REG_Z), \
|
||||
0x00000000}, /* POINTER_REGS, r26 - r31 */ \
|
||||
0x0000000c}, /* POINTER_REGS, r26 - r31 */ \
|
||||
{(3 << REG_X) | (3 << REG_Y) | (3 << REG_Z) | (3 << REG_W), \
|
||||
0x00000000}, /* ADDW_REGS, r24 - r31 */ \
|
||||
{0x00ff0000,0x00000000}, /* SIMPLE_LD_REGS r16 - r23 */ \
|
||||
{(3 << REG_X)|(3 << REG_Y)|(3 << REG_Z)|(3 << REG_W)|(0xff << 16), \
|
||||
0x00000000}, /* LD_REGS, r16 - r31 */ \
|
||||
0x0000000c}, /* LD_REGS, r16 - r31 */ \
|
||||
{0x0000ffff,0x00000000}, /* NO_LD_REGS r0 - r15 */ \
|
||||
{0xffffffff,0x00000000}, /* GENERAL_REGS, r0 - r31 */ \
|
||||
{0xffffffff,0x00000003} /* ALL_REGS */ \
|
||||
{0xffffffff,0x0000000c}, /* GENERAL_REGS, r0 - r31 */ \
|
||||
{0xffffffff,0x0000000f} /* ALL_REGS */ \
|
||||
}
|
||||
|
||||
#define REGNO_REG_CLASS(R) avr_regno_reg_class(R)
|
||||
@ -378,18 +380,20 @@ enum reg_class {
|
||||
|
||||
#define STACK_POINTER_REGNUM 32
|
||||
|
||||
#define FRAME_POINTER_REGNUM REG_Y
|
||||
#define HARD_FRAME_POINTER_REGNUM REG_Y
|
||||
|
||||
#define ARG_POINTER_REGNUM 34
|
||||
#define FRAME_POINTER_REGNUM 35
|
||||
|
||||
#define STATIC_CHAIN_REGNUM 2
|
||||
|
||||
#define ELIMINABLE_REGS { \
|
||||
{ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
|
||||
{FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM} \
|
||||
,{FRAME_POINTER_REGNUM+1,STACK_POINTER_REGNUM+1}}
|
||||
{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM }, \
|
||||
{ ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM }, \
|
||||
{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM }, \
|
||||
{ FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM }}
|
||||
|
||||
#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
|
||||
#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
|
||||
OFFSET = avr_initial_elimination_offset (FROM, TO)
|
||||
|
||||
#define RETURN_ADDR_RTX(count, tem) avr_return_addr_rtx (count, tem)
|
||||
@ -493,7 +497,7 @@ typedef struct avr_args {
|
||||
"r8","r9","r10","r11","r12","r13","r14","r15", \
|
||||
"r16","r17","r18","r19","r20","r21","r22","r23", \
|
||||
"r24","r25","r26","r27","r28","r29","r30","r31", \
|
||||
"__SP_L__","__SP_H__","argL","argH"}
|
||||
"__SP_L__","__SP_H__","ap","fp"}
|
||||
|
||||
#define FINAL_PRESCAN_INSN(insn, operand, nop) final_prescan_insn (insn, operand,nop)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user