Message ID | 20190325110313.9271-3-claziss@gmail.com |
---|---|
State | New |
Headers | show |
Series | Improve register elimination, and other LRA | expand |
* Claudiu Zissulescu <claziss@gmail.com> [2019-03-25 12:03:12 +0100]: > Refurbish eliminable regs howto by introducing a fake > FRAME_POINTER_REGNUM with the purpose to release FP register to be > used freely by the register allocator. > > gcc/ > xxxx-xx-xx Claudiu Zissulescu <claziss@synopsys.com> > > * config/arc/arc.c (arc_hard_regno_modes): Add two missing modes > for last two fake registers. > (arc_conditional_register_usage): Make sure fake frame and arg > pointer regs are in general regs class. > (FRAME_POINTER_MASK): Remove. > (RETURN_ADDR_MASK): Remove. > (arc_must_save_register): Use hard frame regnum. > (frame_restore_reg): Use hard_frame_pointer_rtx. > (arc_save_callee_saves): Likewise. > (arc_restore_callee_saves): Likewise. > (arc_save_callee_enter): Likewise. > (arc_restore_callee_leave): Likewise. > (arc_save_callee_milli): Likewise. > (arc_eh_return_address_location): Likewise. > (arc_check_multi): Use hard frame regnum. > (arc_can_eliminate): Likewise. > * config/arc/arc.h (FIXED_REGISTERS): Make FP register available > for register allocator. > (REG_CLASS_CONTENTS): Update GENERAL_REGS. > (REGNO_OK_FOR_BASE_P): Consider FRAME_POINTER_REGNUM. > (FRAME_POINTER_REGNUM): Change it to a fake register. > (HARD_FRAME_POINTER_REGNUM): Defined. > (ARG_POINTER_REGNUM): Change it to a new fake register. > (ELIMINABLE_REGS): Update. > (REGISTER_NAMES): Update names. > * config/arc/arc.md (LP_START): Remove. > (LP_END): Likewise. > (shift_si3_loop): Update pattern. This is fine, thanks. Andrew > --- > gcc/config/arc/arc.c | 173 +++++++++++++++++++++++------------------- > gcc/config/arc/arc.h | 31 ++++---- > gcc/config/arc/arc.md | 12 +-- > 3 files changed, 115 insertions(+), 101 deletions(-) > > diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c > index 62f435b0a1d..9938a774d91 100644 > --- a/gcc/config/arc/arc.c > +++ b/gcc/config/arc/arc.c > @@ -1651,7 +1651,8 @@ static unsigned int arc_hard_regno_modes[] = { > V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, > > S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, > - S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES > + S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, > + S_MODES, S_MODES > }; > > static unsigned int arc_mode_class [NUM_MACHINE_MODES]; > @@ -1886,7 +1887,8 @@ arc_conditional_register_usage (void) > > /* Handle Special Registers. */ > arc_regno_reg_class[CC_REG] = NO_REGS; /* CC_REG: must be NO_REGS. */ > - arc_regno_reg_class[62] = GENERAL_REGS; > + arc_regno_reg_class[FRAME_POINTER_REGNUM] = GENERAL_REGS; > + arc_regno_reg_class[ARG_POINTER_REGNUM] = GENERAL_REGS; > > if (TARGET_DPFP) > for (i = R40_REG; i < R44_REG; ++i) > @@ -2616,8 +2618,53 @@ arc_compute_function_type (struct function *fun) > return fun->machine->fn_type = fn_type; > } > > -#define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM)) > -#define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM)) > +/* Helper function to wrap FRAME_POINTER_NEEDED. We do this as > + FRAME_POINTER_NEEDED will not be true until the IRA (Integrated > + Register Allocator) pass, while we want to get the frame size > + correct earlier than the IRA pass. > + > + When a function uses eh_return we must ensure that the fp register > + is saved and then restored so that the unwinder can restore the > + correct value for the frame we are going to jump to. > + > + To do this we force all frames that call eh_return to require a > + frame pointer (see arc_frame_pointer_required), this > + will ensure that the previous frame pointer is stored on entry to > + the function, and will then be reloaded at function exit. > + > + As the frame pointer is handled as a special case in our prologue > + and epilogue code it must not be saved and restored using the > + MUST_SAVE_REGISTER mechanism otherwise we run into issues where GCC > + believes that the function is not using a frame pointer and that > + the value in the fp register is the frame pointer, while the > + prologue and epilogue are busy saving and restoring the fp > + register. > + > + During compilation of a function the frame size is evaluated > + multiple times, it is not until the reload pass is complete the the > + frame size is considered fixed (it is at this point that space for > + all spills has been allocated). However the frame_pointer_needed > + variable is not set true until the register allocation pass, as a > + result in the early stages the frame size does not include space > + for the frame pointer to be spilled. > + > + The problem that this causes is that the rtl generated for > + EH_RETURN_HANDLER_RTX uses the details of the frame size to compute > + the offset from the frame pointer at which the return address > + lives. However, in early passes GCC has not yet realised we need a > + frame pointer, and so has not included space for the frame pointer > + in the frame size, and so gets the offset of the return address > + wrong. This should not be an issue as in later passes GCC has > + realised that the frame pointer needs to be spilled, and has > + increased the frame size. However, the rtl for the > + EH_RETURN_HANDLER_RTX is not regenerated to use the newer, larger > + offset, and the wrong smaller offset is used. */ > + > +static bool > +arc_frame_pointer_needed (void) > +{ > + return (frame_pointer_needed || crtl->calls_eh_return); > +} > > /* Tell prologue and epilogue if register REGNO should be saved / restored. > The return address and frame pointer are treated separately. > @@ -2656,16 +2703,28 @@ arc_must_save_register (int regno, struct function *func) > break; > } > > - if ((regno) != RETURN_ADDR_REGNUM > - && (regno) != FRAME_POINTER_REGNUM > - && (regno) != STACK_POINTER_REGNUM > - && df_regs_ever_live_p (regno) > - && (!call_used_regs[regno] > - || ARC_INTERRUPT_P (fn_type)) > - /* Do not emit code for auto saved regs. */ > - && !irq_auto_save_p > - && !firq_auto_save_p) > - return true; > + switch (regno) > + { > + case RETURN_ADDR_REGNUM: > + case STACK_POINTER_REGNUM: > + return false; > + > + case HARD_FRAME_POINTER_REGNUM: > + /* If we need FP reg as a frame pointer then don't save it as a > + regular reg. */ > + if (arc_frame_pointer_needed ()) > + return false; > + > + /* FALLTHRU */ > + default: > + if (df_regs_ever_live_p (regno) > + && (!call_used_regs[regno] > + || ARC_INTERRUPT_P (fn_type)) > + /* Do not emit code for auto saved regs. */ > + && !irq_auto_save_p > + && !firq_auto_save_p) > + return true; > + } > > return false; > } > @@ -2682,54 +2741,6 @@ arc_must_save_return_addr (struct function *func) > return false; > } > > -/* Helper function to wrap FRAME_POINTER_NEEDED. We do this as > - FRAME_POINTER_NEEDED will not be true until the IRA (Integrated > - Register Allocator) pass, while we want to get the frame size > - correct earlier than the IRA pass. > - > - When a function uses eh_return we must ensure that the fp register > - is saved and then restored so that the unwinder can restore the > - correct value for the frame we are going to jump to. > - > - To do this we force all frames that call eh_return to require a > - frame pointer (see arc_frame_pointer_required), this > - will ensure that the previous frame pointer is stored on entry to > - the function, and will then be reloaded at function exit. > - > - As the frame pointer is handled as a special case in our prologue > - and epilogue code it must not be saved and restored using the > - MUST_SAVE_REGISTER mechanism otherwise we run into issues where GCC > - believes that the function is not using a frame pointer and that > - the value in the fp register is the frame pointer, while the > - prologue and epilogue are busy saving and restoring the fp > - register. > - > - During compilation of a function the frame size is evaluated > - multiple times, it is not until the reload pass is complete the the > - frame size is considered fixed (it is at this point that space for > - all spills has been allocated). However the frame_pointer_needed > - variable is not set true until the register allocation pass, as a > - result in the early stages the frame size does not include space > - for the frame pointer to be spilled. > - > - The problem that this causes is that the rtl generated for > - EH_RETURN_HANDLER_RTX uses the details of the frame size to compute > - the offset from the frame pointer at which the return address > - lives. However, in early passes GCC has not yet realised we need a > - frame pointer, and so has not included space for the frame pointer > - in the frame size, and so gets the offset of the return address > - wrong. This should not be an issue as in later passes GCC has > - realised that the frame pointer needs to be spilled, and has > - increased the frame size. However, the rtl for the > - EH_RETURN_HANDLER_RTX is not regenerated to use the newer, larger > - offset, and the wrong smaller offset is used. */ > - > -static bool > -arc_frame_pointer_needed (void) > -{ > - return (frame_pointer_needed || crtl->calls_eh_return); > -} > - > /* Return non-zero if there are registers to be saved or loaded using > millicode thunks. We can only use consecutive sequences starting > with r13, and not going beyond r25. > @@ -2991,7 +3002,7 @@ frame_restore_reg (rtx reg, HOST_WIDE_INT offset) > insn = frame_move_inc (reg, addr, stack_pointer_rtx, 0); > add_reg_note (insn, REG_CFA_RESTORE, reg); > > - if (reg == frame_pointer_rtx) > + if (reg == hard_frame_pointer_rtx) > add_reg_note (insn, REG_CFA_DEF_CFA, > plus_constant (Pmode, stack_pointer_rtx, > GET_MODE_SIZE (GET_MODE (reg)) + offset)); > @@ -3077,13 +3088,13 @@ arc_save_callee_saves (unsigned int gmask, > registers are saved. */ > if (save_fp) > { > - frame_allocated += frame_save_reg (frame_pointer_rtx, offset); > + frame_allocated += frame_save_reg (hard_frame_pointer_rtx, offset); > offset = 0; > } > > /* Emit mov fp,sp. */ > if (arc_frame_pointer_needed ()) > - frame_move (frame_pointer_rtx, stack_pointer_rtx); > + frame_move (hard_frame_pointer_rtx, stack_pointer_rtx); > > return frame_allocated; > } > @@ -3106,7 +3117,7 @@ arc_restore_callee_saves (unsigned int gmask, > /* Emit mov fp,sp. */ > if (arc_frame_pointer_needed () && offset) > { > - frame_move (stack_pointer_rtx, frame_pointer_rtx); > + frame_move (stack_pointer_rtx, hard_frame_pointer_rtx); > frame_deallocated += offset; > offset = 0; > } > @@ -3115,7 +3126,7 @@ arc_restore_callee_saves (unsigned int gmask, > { > /* Any offset is taken care by previous if-statement. */ > gcc_assert (offset == 0); > - frame_deallocated += frame_restore_reg (frame_pointer_rtx, 0); > + frame_deallocated += frame_restore_reg (hard_frame_pointer_rtx, 0); > } > > if (offset) > @@ -3260,11 +3271,11 @@ arc_save_callee_enter (unsigned int gmask, > mem = gen_frame_mem (Pmode, plus_constant (Pmode, > stack_pointer_rtx, > off)); > - XVECEXP (insn, 0, indx) = gen_rtx_SET (mem, frame_pointer_rtx); > + XVECEXP (insn, 0, indx) = gen_rtx_SET (mem, hard_frame_pointer_rtx); > RTX_FRAME_RELATED_P (XVECEXP (insn, 0, indx++)) = 1; > off -= UNITS_PER_WORD; > > - XVECEXP (insn, 0, indx) = gen_rtx_SET (frame_pointer_rtx, > + XVECEXP (insn, 0, indx) = gen_rtx_SET (hard_frame_pointer_rtx, > stack_pointer_rtx); > RTX_FRAME_RELATED_P (XVECEXP (insn, 0, indx++)) = 1; > save_fp = false; > @@ -3368,7 +3379,7 @@ arc_restore_callee_leave (unsigned int gmask, > mem = gen_frame_mem (Pmode, plus_constant (Pmode, > stack_pointer_rtx, > off)); > - XVECEXP (insn, 0, indx) = gen_rtx_SET (frame_pointer_rtx, mem); > + XVECEXP (insn, 0, indx) = gen_rtx_SET (hard_frame_pointer_rtx, mem); > RTX_FRAME_RELATED_P (XVECEXP (insn, 0, indx++)) = 1; > off -= UNITS_PER_WORD; > } > @@ -3387,7 +3398,7 @@ arc_restore_callee_leave (unsigned int gmask, > /* Dwarf related info. */ > if (restore_fp) > { > - add_reg_note (insn, REG_CFA_RESTORE, frame_pointer_rtx); > + add_reg_note (insn, REG_CFA_RESTORE, hard_frame_pointer_rtx); > add_reg_note (insn, REG_CFA_DEF_CFA, > plus_constant (Pmode, stack_pointer_rtx, > offset + nregs * UNITS_PER_WORD)); > @@ -3525,11 +3536,11 @@ arc_save_callee_milli (unsigned int gmask, > above loop to save fp because our ABI states fp goes aftert all > registers are saved. */ > if (save_fp) > - frame_allocated += frame_save_reg (frame_pointer_rtx, offset); > + frame_allocated += frame_save_reg (hard_frame_pointer_rtx, offset); > > /* Emit mov fp,sp. */ > if (arc_frame_pointer_needed ()) > - frame_move (frame_pointer_rtx, stack_pointer_rtx); > + frame_move (hard_frame_pointer_rtx, stack_pointer_rtx); > > return frame_allocated; > } > @@ -3559,13 +3570,13 @@ arc_restore_callee_milli (unsigned int gmask, > /* Emit mov fp,sp. */ > if (arc_frame_pointer_needed () && offset) > { > - frame_move (stack_pointer_rtx, frame_pointer_rtx); > + frame_move (stack_pointer_rtx, hard_frame_pointer_rtx); > frame_allocated = offset; > offset = 0; > } > > if (restore_fp) > - frame_allocated += frame_restore_reg (frame_pointer_rtx, 0); > + frame_allocated += frame_restore_reg (hard_frame_pointer_rtx, 0); > > if (offset) > { > @@ -3875,7 +3886,7 @@ arc_check_multi (rtx op, bool push_p) > if (REGNO (reg) == RETURN_ADDR_REGNUM > && i == start) > regno = 12; > - else if (REGNO (reg) == FRAME_POINTER_REGNUM) > + else if (REGNO (reg) == HARD_FRAME_POINTER_REGNUM) > ++i; > else if (REGNO (reg) != regno) > return false; > @@ -3922,7 +3933,7 @@ arc_eh_return_address_location (rtx source) > included in the 'extra_size' field. */ > offset = afi->reg_size + afi->extra_size - 4; > mem = gen_frame_mem (Pmode, > - plus_constant (Pmode, frame_pointer_rtx, offset)); > + plus_constant (Pmode, hard_frame_pointer_rtx, offset)); > > /* The following should not be needed, and is, really a hack. The > issue being worked around here is that the DSE (Dead Store > @@ -5396,7 +5407,7 @@ arc_final_prescan_insn (rtx_insn *insn, rtx *opvec ATTRIBUTE_UNUSED, > static bool > arc_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to) > { > - return ((to == FRAME_POINTER_REGNUM) || !arc_frame_pointer_needed ()); > + return ((to == HARD_FRAME_POINTER_REGNUM) || (to == STACK_POINTER_REGNUM)); > } > > /* Define the offset between two registers, one to be eliminated, and > @@ -5408,7 +5419,7 @@ arc_initial_elimination_offset (int from, int to) > if (!cfun->machine->frame_info.initialized) > arc_compute_frame_size (); > > - if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM) > + if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM) > { > return (cfun->machine->frame_info.extra_size > + cfun->machine->frame_info.reg_size); > @@ -5427,6 +5438,8 @@ arc_initial_elimination_offset (int from, int to) > + cfun->machine->frame_info.extra_size > + cfun->machine->frame_info.reg_size)); > } > + if ((from == FRAME_POINTER_REGNUM) && (to == HARD_FRAME_POINTER_REGNUM)) > + return 0; > > gcc_unreachable (); > } > @@ -11024,7 +11037,7 @@ arc_builtin_setjmp_frame_value (void) > frame pointer value for this frame (if the use of the frame pointer > had not been removed). We really do want the raw frame pointer > register value. */ > - return gen_raw_REG (Pmode, FRAME_POINTER_REGNUM); > + return gen_raw_REG (Pmode, HARD_FRAME_POINTER_REGNUM); > } > > /* Return nonzero if a jli call should be generated for a call from > diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h > index 6a77869b58c..fbe71278346 100644 > --- a/gcc/config/arc/arc.h > +++ b/gcc/config/arc/arc.h > @@ -325,7 +325,7 @@ if (GET_MODE_CLASS (MODE) == MODE_INT \ > argument pointer. */ > > /* r63 is pc, r64-r127 = simd vregs, r128-r143 = simd dma config regs > - r144, r145 = lp_start, lp_end > + r144, r145 = ARG_POINTER, FRAME_POINTER > and therefore the pseudo registers start from r146. */ > #define FIRST_PSEUDO_REGISTER 146 > > @@ -366,7 +366,7 @@ if (GET_MODE_CLASS (MODE) == MODE_INT \ > { 0, 0, 0, 0, 0, 0, 0, 0, \ > 0, 0, 0, 0, 0, 0, 0, 0, \ > 0, 0, 0, 0, 0, 0, 0, 0, \ > - 0, 0, 1, 1, 1, 1, 1, 1, \ > + 0, 0, 1, 0, 1, 1, 1, 1, \ > \ > 1, 1, 1, 1, 1, 1, 1, 1, \ > 0, 0, 0, 0, 1, 1, 1, 1, \ > @@ -398,7 +398,7 @@ if (GET_MODE_CLASS (MODE) == MODE_INT \ > 1, 1, 1, 1, 1, 1, 1, 1, \ > 1, 1, 1, 1, 1, 0, 0, 0, \ > 0, 0, 0, 0, 0, 0, 0, 0, \ > - 0, 0, 1, 1, 1, 1, 1, 1, \ > + 0, 0, 1, 0, 1, 1, 1, 1, \ > \ > 1, 1, 1, 1, 1, 1, 1, 1, \ > 1, 1, 1, 1, 1, 1, 1, 1, \ > @@ -511,10 +511,10 @@ enum reg_class > {0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'Rsd'. */ \ > {0x0000000f, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'Rcd'. */ \ > {0x0000f00f, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'q'. */ \ > - {0x1c001fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'Rsc'. */ \ > + {0x00001fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'Rsc'. */ \ > {0x9fffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'h'. */ \ > {0x00000000, 0x00000f00, 0x00000000, 0x00000000, 0x00000000}, /* 'D'. */ \ > - {0xffffffff, 0x8fffffff, 0x00000000, 0x00000000, 0x00000000}, /* 'r'. */ \ > + {0xffffffff, 0x8fffffff, 0x00000000, 0x00000000, 0x00030000}, /* 'r'. */ \ > {0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000}, /* 'v'. */ \ > {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff}, /* 'd'. */ \ > {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0003ffff} /* ALL_REGS. */\ > @@ -562,11 +562,14 @@ extern enum reg_class arc_regno_reg_class[]; > Since they use reg_renumber, they are safe only once reg_renumber > has been allocated, which happens in local-alloc.c. */ > #define REGNO_OK_FOR_BASE_P(REGNO) \ > - ((REGNO) < 29 || ((REGNO) == ARG_POINTER_REGNUM) || ((REGNO) == 63) \ > + ((REGNO) < 29 \ > + || ((REGNO) == ARG_POINTER_REGNUM) \ > + || ((REGNO) == FRAME_POINTER_REGNUM) \ > + || ((REGNO) == PCL_REG) \ > || ((unsigned) reg_renumber[REGNO] < 29) \ > || ((unsigned) (REGNO) == (unsigned) arc_tp_regno) \ > || (fixed_regs[REGNO] == 0 && IN_RANGE (REGNO, 32, 59)) \ > - || ((REGNO) == 30 && fixed_regs[REGNO] == 0)) > + || (fixed_regs[REGNO] == 0 && (REGNO) == R30_REG)) > > #define REGNO_OK_FOR_INDEX_P(REGNO) REGNO_OK_FOR_BASE_P(REGNO) > > @@ -652,11 +655,12 @@ arc_return_addr_rtx(COUNT,FRAME) > #define STACK_POINTER_REGNUM 28 > > /* Base register for access to local variables of the function. */ > -#define FRAME_POINTER_REGNUM 27 > +#define FRAME_POINTER_REGNUM 145 > +#define HARD_FRAME_POINTER_REGNUM 27 > > /* Base register for access to arguments of the function. This register > will be eliminated into either fp or sp. */ > -#define ARG_POINTER_REGNUM 62 > +#define ARG_POINTER_REGNUM 144 > > #define RETURN_ADDR_REGNUM 31 > > @@ -766,8 +770,9 @@ arc_return_addr_rtx(COUNT,FRAME) > > #define ELIMINABLE_REGS \ > {{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ > - {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ > - {FRAME_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 the offset between two registers, one to be eliminated, and the other > its replacement, at the start of a routine. */ > @@ -1161,7 +1166,7 @@ extern char rname56[], rname57[], rname58[], rname59[]; > "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39", \ > "d1", "d1", "d2", "d2", "r44", "r45", "r46", "r47", \ > "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55", \ > - rname56,rname57,rname58,rname59,"lp_count", "cc", "ap", "pcl", \ > + rname56,rname57,rname58,rname59,"lp_count", "cc", "limm", "pcl", \ > "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7", \ > "vr8", "vr9", "vr10", "vr11", "vr12", "vr13", "vr14", "vr15", \ > "vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23", \ > @@ -1172,7 +1177,7 @@ extern char rname56[], rname57[], rname58[], rname59[]; > "vr56", "vr57", "vr58", "vr59", "vr60", "vr61", "vr62", "vr63", \ > "dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7", \ > "dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7", \ > - "lp_start", "lp_end" \ > + "arg", "frame" \ > } > > #define ADDITIONAL_REGISTER_NAMES \ > diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md > index 3a903d4224a..7ac5a1b5785 100644 > --- a/gcc/config/arc/arc.md > +++ b/gcc/config/arc/arc.md > @@ -202,8 +202,6 @@ > (LP_COUNT 60) > (CC_REG 61) > (PCL_REG 63) > - (LP_START 144) > - (LP_END 145) > ] > ) > > @@ -3467,8 +3465,6 @@ core_3, archs4x, archs4xd, archs4xd_slow" > (match_operand:SI 2 "nonmemory_operand" "rn,Cal")])) > (clobber (match_scratch:SI 4 "=X,X")) > (clobber (reg:SI LP_COUNT)) > - (clobber (reg:SI LP_START)) > - (clobber (reg:SI LP_END)) > (clobber (reg:CC CC_REG)) > ] > "!TARGET_BARREL_SHIFTER" > @@ -6508,7 +6504,7 @@ core_3, archs4x, archs4xd, archs4xd_slow" > { > int len = XVECLEN (operands[0], 0); > rtx tmp = XVECEXP (operands[0], 0, len - 1); > - if (XEXP (tmp, 0) != frame_pointer_rtx) > + if (XEXP (tmp, 0) != hard_frame_pointer_rtx) > { > operands[3] = XEXP (tmp, 0); > gcc_assert (INTVAL (operands[1]) == INTVAL (operands[2])); > @@ -6538,7 +6534,7 @@ core_3, archs4x, archs4xd, archs4xd_slow" > { > int len = XVECLEN (operands[0], 0); > rtx tmp = XVECEXP (operands[0], 0, len - 1); > - if (XEXP (tmp, 0) != frame_pointer_rtx) > + if (XEXP (tmp, 0) != hard_frame_pointer_rtx) > { > operands[3] = XEXP (tmp, 0); > gcc_assert (INTVAL (operands[1]) == INTVAL (operands[2])); > @@ -6569,7 +6565,7 @@ core_3, archs4x, archs4xd, archs4xd_slow" > { > int len = XVECLEN (operands[0], 0); > rtx tmp = XVECEXP (operands[0], 0, len - 1); > - if (XEXP (tmp, 0) != frame_pointer_rtx) > + if (XEXP (tmp, 0) != hard_frame_pointer_rtx) > { > operands[3] = XEXP (tmp, 0); > gcc_assert (INTVAL (operands[1]) == INTVAL (operands[2])); > @@ -6600,7 +6596,7 @@ core_3, archs4x, archs4xd, archs4xd_slow" > { > int len = XVECLEN (operands[0], 0); > rtx tmp = XVECEXP (operands[0], 0, len - 1); > - if (XEXP (tmp, 0) != frame_pointer_rtx) > + if (XEXP (tmp, 0) != hard_frame_pointer_rtx) > { > operands[3] = XEXP (tmp, 0); > gcc_assert (INTVAL (operands[1]) == INTVAL (operands[2])); > -- > 2.20.1 >
Committed. Thank you, Claudiu On Thu, Apr 11, 2019 at 12:54 AM Andrew Burgess <andrew.burgess@embecosm.com> wrote: > > * Claudiu Zissulescu <claziss@gmail.com> [2019-03-25 12:03:12 +0100]: > > > Refurbish eliminable regs howto by introducing a fake > > FRAME_POINTER_REGNUM with the purpose to release FP register to be > > used freely by the register allocator. > > > > gcc/ > > xxxx-xx-xx Claudiu Zissulescu <claziss@synopsys.com> > > > > * config/arc/arc.c (arc_hard_regno_modes): Add two missing modes > > for last two fake registers. > > (arc_conditional_register_usage): Make sure fake frame and arg > > pointer regs are in general regs class. > > (FRAME_POINTER_MASK): Remove. > > (RETURN_ADDR_MASK): Remove. > > (arc_must_save_register): Use hard frame regnum. > > (frame_restore_reg): Use hard_frame_pointer_rtx. > > (arc_save_callee_saves): Likewise. > > (arc_restore_callee_saves): Likewise. > > (arc_save_callee_enter): Likewise. > > (arc_restore_callee_leave): Likewise. > > (arc_save_callee_milli): Likewise. > > (arc_eh_return_address_location): Likewise. > > (arc_check_multi): Use hard frame regnum. > > (arc_can_eliminate): Likewise. > > * config/arc/arc.h (FIXED_REGISTERS): Make FP register available > > for register allocator. > > (REG_CLASS_CONTENTS): Update GENERAL_REGS. > > (REGNO_OK_FOR_BASE_P): Consider FRAME_POINTER_REGNUM. > > (FRAME_POINTER_REGNUM): Change it to a fake register. > > (HARD_FRAME_POINTER_REGNUM): Defined. > > (ARG_POINTER_REGNUM): Change it to a new fake register. > > (ELIMINABLE_REGS): Update. > > (REGISTER_NAMES): Update names. > > * config/arc/arc.md (LP_START): Remove. > > (LP_END): Likewise. > > (shift_si3_loop): Update pattern. > > This is fine, thanks. > > Andrew > > > > --- > > gcc/config/arc/arc.c | 173 +++++++++++++++++++++++------------------- > > gcc/config/arc/arc.h | 31 ++++---- > > gcc/config/arc/arc.md | 12 +-- > > 3 files changed, 115 insertions(+), 101 deletions(-) > > > > diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c > > index 62f435b0a1d..9938a774d91 100644 > > --- a/gcc/config/arc/arc.c > > +++ b/gcc/config/arc/arc.c > > @@ -1651,7 +1651,8 @@ static unsigned int arc_hard_regno_modes[] = { > > V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, > > > > S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, > > - S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES > > + S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, > > + S_MODES, S_MODES > > }; > > > > static unsigned int arc_mode_class [NUM_MACHINE_MODES]; > > @@ -1886,7 +1887,8 @@ arc_conditional_register_usage (void) > > > > /* Handle Special Registers. */ > > arc_regno_reg_class[CC_REG] = NO_REGS; /* CC_REG: must be NO_REGS. */ > > - arc_regno_reg_class[62] = GENERAL_REGS; > > + arc_regno_reg_class[FRAME_POINTER_REGNUM] = GENERAL_REGS; > > + arc_regno_reg_class[ARG_POINTER_REGNUM] = GENERAL_REGS; > > > > if (TARGET_DPFP) > > for (i = R40_REG; i < R44_REG; ++i) > > @@ -2616,8 +2618,53 @@ arc_compute_function_type (struct function *fun) > > return fun->machine->fn_type = fn_type; > > } > > > > -#define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM)) > > -#define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM)) > > +/* Helper function to wrap FRAME_POINTER_NEEDED. We do this as > > + FRAME_POINTER_NEEDED will not be true until the IRA (Integrated > > + Register Allocator) pass, while we want to get the frame size > > + correct earlier than the IRA pass. > > + > > + When a function uses eh_return we must ensure that the fp register > > + is saved and then restored so that the unwinder can restore the > > + correct value for the frame we are going to jump to. > > + > > + To do this we force all frames that call eh_return to require a > > + frame pointer (see arc_frame_pointer_required), this > > + will ensure that the previous frame pointer is stored on entry to > > + the function, and will then be reloaded at function exit. > > + > > + As the frame pointer is handled as a special case in our prologue > > + and epilogue code it must not be saved and restored using the > > + MUST_SAVE_REGISTER mechanism otherwise we run into issues where GCC > > + believes that the function is not using a frame pointer and that > > + the value in the fp register is the frame pointer, while the > > + prologue and epilogue are busy saving and restoring the fp > > + register. > > + > > + During compilation of a function the frame size is evaluated > > + multiple times, it is not until the reload pass is complete the the > > + frame size is considered fixed (it is at this point that space for > > + all spills has been allocated). However the frame_pointer_needed > > + variable is not set true until the register allocation pass, as a > > + result in the early stages the frame size does not include space > > + for the frame pointer to be spilled. > > + > > + The problem that this causes is that the rtl generated for > > + EH_RETURN_HANDLER_RTX uses the details of the frame size to compute > > + the offset from the frame pointer at which the return address > > + lives. However, in early passes GCC has not yet realised we need a > > + frame pointer, and so has not included space for the frame pointer > > + in the frame size, and so gets the offset of the return address > > + wrong. This should not be an issue as in later passes GCC has > > + realised that the frame pointer needs to be spilled, and has > > + increased the frame size. However, the rtl for the > > + EH_RETURN_HANDLER_RTX is not regenerated to use the newer, larger > > + offset, and the wrong smaller offset is used. */ > > + > > +static bool > > +arc_frame_pointer_needed (void) > > +{ > > + return (frame_pointer_needed || crtl->calls_eh_return); > > +} > > > > /* Tell prologue and epilogue if register REGNO should be saved / restored. > > The return address and frame pointer are treated separately. > > @@ -2656,16 +2703,28 @@ arc_must_save_register (int regno, struct function *func) > > break; > > } > > > > - if ((regno) != RETURN_ADDR_REGNUM > > - && (regno) != FRAME_POINTER_REGNUM > > - && (regno) != STACK_POINTER_REGNUM > > - && df_regs_ever_live_p (regno) > > - && (!call_used_regs[regno] > > - || ARC_INTERRUPT_P (fn_type)) > > - /* Do not emit code for auto saved regs. */ > > - && !irq_auto_save_p > > - && !firq_auto_save_p) > > - return true; > > + switch (regno) > > + { > > + case RETURN_ADDR_REGNUM: > > + case STACK_POINTER_REGNUM: > > + return false; > > + > > + case HARD_FRAME_POINTER_REGNUM: > > + /* If we need FP reg as a frame pointer then don't save it as a > > + regular reg. */ > > + if (arc_frame_pointer_needed ()) > > + return false; > > + > > + /* FALLTHRU */ > > + default: > > + if (df_regs_ever_live_p (regno) > > + && (!call_used_regs[regno] > > + || ARC_INTERRUPT_P (fn_type)) > > + /* Do not emit code for auto saved regs. */ > > + && !irq_auto_save_p > > + && !firq_auto_save_p) > > + return true; > > + } > > > > return false; > > } > > @@ -2682,54 +2741,6 @@ arc_must_save_return_addr (struct function *func) > > return false; > > } > > > > -/* Helper function to wrap FRAME_POINTER_NEEDED. We do this as > > - FRAME_POINTER_NEEDED will not be true until the IRA (Integrated > > - Register Allocator) pass, while we want to get the frame size > > - correct earlier than the IRA pass. > > - > > - When a function uses eh_return we must ensure that the fp register > > - is saved and then restored so that the unwinder can restore the > > - correct value for the frame we are going to jump to. > > - > > - To do this we force all frames that call eh_return to require a > > - frame pointer (see arc_frame_pointer_required), this > > - will ensure that the previous frame pointer is stored on entry to > > - the function, and will then be reloaded at function exit. > > - > > - As the frame pointer is handled as a special case in our prologue > > - and epilogue code it must not be saved and restored using the > > - MUST_SAVE_REGISTER mechanism otherwise we run into issues where GCC > > - believes that the function is not using a frame pointer and that > > - the value in the fp register is the frame pointer, while the > > - prologue and epilogue are busy saving and restoring the fp > > - register. > > - > > - During compilation of a function the frame size is evaluated > > - multiple times, it is not until the reload pass is complete the the > > - frame size is considered fixed (it is at this point that space for > > - all spills has been allocated). However the frame_pointer_needed > > - variable is not set true until the register allocation pass, as a > > - result in the early stages the frame size does not include space > > - for the frame pointer to be spilled. > > - > > - The problem that this causes is that the rtl generated for > > - EH_RETURN_HANDLER_RTX uses the details of the frame size to compute > > - the offset from the frame pointer at which the return address > > - lives. However, in early passes GCC has not yet realised we need a > > - frame pointer, and so has not included space for the frame pointer > > - in the frame size, and so gets the offset of the return address > > - wrong. This should not be an issue as in later passes GCC has > > - realised that the frame pointer needs to be spilled, and has > > - increased the frame size. However, the rtl for the > > - EH_RETURN_HANDLER_RTX is not regenerated to use the newer, larger > > - offset, and the wrong smaller offset is used. */ > > - > > -static bool > > -arc_frame_pointer_needed (void) > > -{ > > - return (frame_pointer_needed || crtl->calls_eh_return); > > -} > > - > > /* Return non-zero if there are registers to be saved or loaded using > > millicode thunks. We can only use consecutive sequences starting > > with r13, and not going beyond r25. > > @@ -2991,7 +3002,7 @@ frame_restore_reg (rtx reg, HOST_WIDE_INT offset) > > insn = frame_move_inc (reg, addr, stack_pointer_rtx, 0); > > add_reg_note (insn, REG_CFA_RESTORE, reg); > > > > - if (reg == frame_pointer_rtx) > > + if (reg == hard_frame_pointer_rtx) > > add_reg_note (insn, REG_CFA_DEF_CFA, > > plus_constant (Pmode, stack_pointer_rtx, > > GET_MODE_SIZE (GET_MODE (reg)) + offset)); > > @@ -3077,13 +3088,13 @@ arc_save_callee_saves (unsigned int gmask, > > registers are saved. */ > > if (save_fp) > > { > > - frame_allocated += frame_save_reg (frame_pointer_rtx, offset); > > + frame_allocated += frame_save_reg (hard_frame_pointer_rtx, offset); > > offset = 0; > > } > > > > /* Emit mov fp,sp. */ > > if (arc_frame_pointer_needed ()) > > - frame_move (frame_pointer_rtx, stack_pointer_rtx); > > + frame_move (hard_frame_pointer_rtx, stack_pointer_rtx); > > > > return frame_allocated; > > } > > @@ -3106,7 +3117,7 @@ arc_restore_callee_saves (unsigned int gmask, > > /* Emit mov fp,sp. */ > > if (arc_frame_pointer_needed () && offset) > > { > > - frame_move (stack_pointer_rtx, frame_pointer_rtx); > > + frame_move (stack_pointer_rtx, hard_frame_pointer_rtx); > > frame_deallocated += offset; > > offset = 0; > > } > > @@ -3115,7 +3126,7 @@ arc_restore_callee_saves (unsigned int gmask, > > { > > /* Any offset is taken care by previous if-statement. */ > > gcc_assert (offset == 0); > > - frame_deallocated += frame_restore_reg (frame_pointer_rtx, 0); > > + frame_deallocated += frame_restore_reg (hard_frame_pointer_rtx, 0); > > } > > > > if (offset) > > @@ -3260,11 +3271,11 @@ arc_save_callee_enter (unsigned int gmask, > > mem = gen_frame_mem (Pmode, plus_constant (Pmode, > > stack_pointer_rtx, > > off)); > > - XVECEXP (insn, 0, indx) = gen_rtx_SET (mem, frame_pointer_rtx); > > + XVECEXP (insn, 0, indx) = gen_rtx_SET (mem, hard_frame_pointer_rtx); > > RTX_FRAME_RELATED_P (XVECEXP (insn, 0, indx++)) = 1; > > off -= UNITS_PER_WORD; > > > > - XVECEXP (insn, 0, indx) = gen_rtx_SET (frame_pointer_rtx, > > + XVECEXP (insn, 0, indx) = gen_rtx_SET (hard_frame_pointer_rtx, > > stack_pointer_rtx); > > RTX_FRAME_RELATED_P (XVECEXP (insn, 0, indx++)) = 1; > > save_fp = false; > > @@ -3368,7 +3379,7 @@ arc_restore_callee_leave (unsigned int gmask, > > mem = gen_frame_mem (Pmode, plus_constant (Pmode, > > stack_pointer_rtx, > > off)); > > - XVECEXP (insn, 0, indx) = gen_rtx_SET (frame_pointer_rtx, mem); > > + XVECEXP (insn, 0, indx) = gen_rtx_SET (hard_frame_pointer_rtx, mem); > > RTX_FRAME_RELATED_P (XVECEXP (insn, 0, indx++)) = 1; > > off -= UNITS_PER_WORD; > > } > > @@ -3387,7 +3398,7 @@ arc_restore_callee_leave (unsigned int gmask, > > /* Dwarf related info. */ > > if (restore_fp) > > { > > - add_reg_note (insn, REG_CFA_RESTORE, frame_pointer_rtx); > > + add_reg_note (insn, REG_CFA_RESTORE, hard_frame_pointer_rtx); > > add_reg_note (insn, REG_CFA_DEF_CFA, > > plus_constant (Pmode, stack_pointer_rtx, > > offset + nregs * UNITS_PER_WORD)); > > @@ -3525,11 +3536,11 @@ arc_save_callee_milli (unsigned int gmask, > > above loop to save fp because our ABI states fp goes aftert all > > registers are saved. */ > > if (save_fp) > > - frame_allocated += frame_save_reg (frame_pointer_rtx, offset); > > + frame_allocated += frame_save_reg (hard_frame_pointer_rtx, offset); > > > > /* Emit mov fp,sp. */ > > if (arc_frame_pointer_needed ()) > > - frame_move (frame_pointer_rtx, stack_pointer_rtx); > > + frame_move (hard_frame_pointer_rtx, stack_pointer_rtx); > > > > return frame_allocated; > > } > > @@ -3559,13 +3570,13 @@ arc_restore_callee_milli (unsigned int gmask, > > /* Emit mov fp,sp. */ > > if (arc_frame_pointer_needed () && offset) > > { > > - frame_move (stack_pointer_rtx, frame_pointer_rtx); > > + frame_move (stack_pointer_rtx, hard_frame_pointer_rtx); > > frame_allocated = offset; > > offset = 0; > > } > > > > if (restore_fp) > > - frame_allocated += frame_restore_reg (frame_pointer_rtx, 0); > > + frame_allocated += frame_restore_reg (hard_frame_pointer_rtx, 0); > > > > if (offset) > > { > > @@ -3875,7 +3886,7 @@ arc_check_multi (rtx op, bool push_p) > > if (REGNO (reg) == RETURN_ADDR_REGNUM > > && i == start) > > regno = 12; > > - else if (REGNO (reg) == FRAME_POINTER_REGNUM) > > + else if (REGNO (reg) == HARD_FRAME_POINTER_REGNUM) > > ++i; > > else if (REGNO (reg) != regno) > > return false; > > @@ -3922,7 +3933,7 @@ arc_eh_return_address_location (rtx source) > > included in the 'extra_size' field. */ > > offset = afi->reg_size + afi->extra_size - 4; > > mem = gen_frame_mem (Pmode, > > - plus_constant (Pmode, frame_pointer_rtx, offset)); > > + plus_constant (Pmode, hard_frame_pointer_rtx, offset)); > > > > /* The following should not be needed, and is, really a hack. The > > issue being worked around here is that the DSE (Dead Store > > @@ -5396,7 +5407,7 @@ arc_final_prescan_insn (rtx_insn *insn, rtx *opvec ATTRIBUTE_UNUSED, > > static bool > > arc_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to) > > { > > - return ((to == FRAME_POINTER_REGNUM) || !arc_frame_pointer_needed ()); > > + return ((to == HARD_FRAME_POINTER_REGNUM) || (to == STACK_POINTER_REGNUM)); > > } > > > > /* Define the offset between two registers, one to be eliminated, and > > @@ -5408,7 +5419,7 @@ arc_initial_elimination_offset (int from, int to) > > if (!cfun->machine->frame_info.initialized) > > arc_compute_frame_size (); > > > > - if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM) > > + if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM) > > { > > return (cfun->machine->frame_info.extra_size > > + cfun->machine->frame_info.reg_size); > > @@ -5427,6 +5438,8 @@ arc_initial_elimination_offset (int from, int to) > > + cfun->machine->frame_info.extra_size > > + cfun->machine->frame_info.reg_size)); > > } > > + if ((from == FRAME_POINTER_REGNUM) && (to == HARD_FRAME_POINTER_REGNUM)) > > + return 0; > > > > gcc_unreachable (); > > } > > @@ -11024,7 +11037,7 @@ arc_builtin_setjmp_frame_value (void) > > frame pointer value for this frame (if the use of the frame pointer > > had not been removed). We really do want the raw frame pointer > > register value. */ > > - return gen_raw_REG (Pmode, FRAME_POINTER_REGNUM); > > + return gen_raw_REG (Pmode, HARD_FRAME_POINTER_REGNUM); > > } > > > > /* Return nonzero if a jli call should be generated for a call from > > diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h > > index 6a77869b58c..fbe71278346 100644 > > --- a/gcc/config/arc/arc.h > > +++ b/gcc/config/arc/arc.h > > @@ -325,7 +325,7 @@ if (GET_MODE_CLASS (MODE) == MODE_INT \ > > argument pointer. */ > > > > /* r63 is pc, r64-r127 = simd vregs, r128-r143 = simd dma config regs > > - r144, r145 = lp_start, lp_end > > + r144, r145 = ARG_POINTER, FRAME_POINTER > > and therefore the pseudo registers start from r146. */ > > #define FIRST_PSEUDO_REGISTER 146 > > > > @@ -366,7 +366,7 @@ if (GET_MODE_CLASS (MODE) == MODE_INT \ > > { 0, 0, 0, 0, 0, 0, 0, 0, \ > > 0, 0, 0, 0, 0, 0, 0, 0, \ > > 0, 0, 0, 0, 0, 0, 0, 0, \ > > - 0, 0, 1, 1, 1, 1, 1, 1, \ > > + 0, 0, 1, 0, 1, 1, 1, 1, \ > > \ > > 1, 1, 1, 1, 1, 1, 1, 1, \ > > 0, 0, 0, 0, 1, 1, 1, 1, \ > > @@ -398,7 +398,7 @@ if (GET_MODE_CLASS (MODE) == MODE_INT \ > > 1, 1, 1, 1, 1, 1, 1, 1, \ > > 1, 1, 1, 1, 1, 0, 0, 0, \ > > 0, 0, 0, 0, 0, 0, 0, 0, \ > > - 0, 0, 1, 1, 1, 1, 1, 1, \ > > + 0, 0, 1, 0, 1, 1, 1, 1, \ > > \ > > 1, 1, 1, 1, 1, 1, 1, 1, \ > > 1, 1, 1, 1, 1, 1, 1, 1, \ > > @@ -511,10 +511,10 @@ enum reg_class > > {0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'Rsd'. */ \ > > {0x0000000f, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'Rcd'. */ \ > > {0x0000f00f, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'q'. */ \ > > - {0x1c001fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'Rsc'. */ \ > > + {0x00001fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'Rsc'. */ \ > > {0x9fffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'h'. */ \ > > {0x00000000, 0x00000f00, 0x00000000, 0x00000000, 0x00000000}, /* 'D'. */ \ > > - {0xffffffff, 0x8fffffff, 0x00000000, 0x00000000, 0x00000000}, /* 'r'. */ \ > > + {0xffffffff, 0x8fffffff, 0x00000000, 0x00000000, 0x00030000}, /* 'r'. */ \ > > {0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000}, /* 'v'. */ \ > > {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff}, /* 'd'. */ \ > > {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0003ffff} /* ALL_REGS. */\ > > @@ -562,11 +562,14 @@ extern enum reg_class arc_regno_reg_class[]; > > Since they use reg_renumber, they are safe only once reg_renumber > > has been allocated, which happens in local-alloc.c. */ > > #define REGNO_OK_FOR_BASE_P(REGNO) \ > > - ((REGNO) < 29 || ((REGNO) == ARG_POINTER_REGNUM) || ((REGNO) == 63) \ > > + ((REGNO) < 29 \ > > + || ((REGNO) == ARG_POINTER_REGNUM) \ > > + || ((REGNO) == FRAME_POINTER_REGNUM) \ > > + || ((REGNO) == PCL_REG) \ > > || ((unsigned) reg_renumber[REGNO] < 29) \ > > || ((unsigned) (REGNO) == (unsigned) arc_tp_regno) \ > > || (fixed_regs[REGNO] == 0 && IN_RANGE (REGNO, 32, 59)) \ > > - || ((REGNO) == 30 && fixed_regs[REGNO] == 0)) > > + || (fixed_regs[REGNO] == 0 && (REGNO) == R30_REG)) > > > > #define REGNO_OK_FOR_INDEX_P(REGNO) REGNO_OK_FOR_BASE_P(REGNO) > > > > @@ -652,11 +655,12 @@ arc_return_addr_rtx(COUNT,FRAME) > > #define STACK_POINTER_REGNUM 28 > > > > /* Base register for access to local variables of the function. */ > > -#define FRAME_POINTER_REGNUM 27 > > +#define FRAME_POINTER_REGNUM 145 > > +#define HARD_FRAME_POINTER_REGNUM 27 > > > > /* Base register for access to arguments of the function. This register > > will be eliminated into either fp or sp. */ > > -#define ARG_POINTER_REGNUM 62 > > +#define ARG_POINTER_REGNUM 144 > > > > #define RETURN_ADDR_REGNUM 31 > > > > @@ -766,8 +770,9 @@ arc_return_addr_rtx(COUNT,FRAME) > > > > #define ELIMINABLE_REGS \ > > {{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ > > - {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ > > - {FRAME_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 the offset between two registers, one to be eliminated, and the other > > its replacement, at the start of a routine. */ > > @@ -1161,7 +1166,7 @@ extern char rname56[], rname57[], rname58[], rname59[]; > > "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39", \ > > "d1", "d1", "d2", "d2", "r44", "r45", "r46", "r47", \ > > "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55", \ > > - rname56,rname57,rname58,rname59,"lp_count", "cc", "ap", "pcl", \ > > + rname56,rname57,rname58,rname59,"lp_count", "cc", "limm", "pcl", \ > > "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7", \ > > "vr8", "vr9", "vr10", "vr11", "vr12", "vr13", "vr14", "vr15", \ > > "vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23", \ > > @@ -1172,7 +1177,7 @@ extern char rname56[], rname57[], rname58[], rname59[]; > > "vr56", "vr57", "vr58", "vr59", "vr60", "vr61", "vr62", "vr63", \ > > "dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7", \ > > "dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7", \ > > - "lp_start", "lp_end" \ > > + "arg", "frame" \ > > } > > > > #define ADDITIONAL_REGISTER_NAMES \ > > diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md > > index 3a903d4224a..7ac5a1b5785 100644 > > --- a/gcc/config/arc/arc.md > > +++ b/gcc/config/arc/arc.md > > @@ -202,8 +202,6 @@ > > (LP_COUNT 60) > > (CC_REG 61) > > (PCL_REG 63) > > - (LP_START 144) > > - (LP_END 145) > > ] > > ) > > > > @@ -3467,8 +3465,6 @@ core_3, archs4x, archs4xd, archs4xd_slow" > > (match_operand:SI 2 "nonmemory_operand" "rn,Cal")])) > > (clobber (match_scratch:SI 4 "=X,X")) > > (clobber (reg:SI LP_COUNT)) > > - (clobber (reg:SI LP_START)) > > - (clobber (reg:SI LP_END)) > > (clobber (reg:CC CC_REG)) > > ] > > "!TARGET_BARREL_SHIFTER" > > @@ -6508,7 +6504,7 @@ core_3, archs4x, archs4xd, archs4xd_slow" > > { > > int len = XVECLEN (operands[0], 0); > > rtx tmp = XVECEXP (operands[0], 0, len - 1); > > - if (XEXP (tmp, 0) != frame_pointer_rtx) > > + if (XEXP (tmp, 0) != hard_frame_pointer_rtx) > > { > > operands[3] = XEXP (tmp, 0); > > gcc_assert (INTVAL (operands[1]) == INTVAL (operands[2])); > > @@ -6538,7 +6534,7 @@ core_3, archs4x, archs4xd, archs4xd_slow" > > { > > int len = XVECLEN (operands[0], 0); > > rtx tmp = XVECEXP (operands[0], 0, len - 1); > > - if (XEXP (tmp, 0) != frame_pointer_rtx) > > + if (XEXP (tmp, 0) != hard_frame_pointer_rtx) > > { > > operands[3] = XEXP (tmp, 0); > > gcc_assert (INTVAL (operands[1]) == INTVAL (operands[2])); > > @@ -6569,7 +6565,7 @@ core_3, archs4x, archs4xd, archs4xd_slow" > > { > > int len = XVECLEN (operands[0], 0); > > rtx tmp = XVECEXP (operands[0], 0, len - 1); > > - if (XEXP (tmp, 0) != frame_pointer_rtx) > > + if (XEXP (tmp, 0) != hard_frame_pointer_rtx) > > { > > operands[3] = XEXP (tmp, 0); > > gcc_assert (INTVAL (operands[1]) == INTVAL (operands[2])); > > @@ -6600,7 +6596,7 @@ core_3, archs4x, archs4xd, archs4xd_slow" > > { > > int len = XVECLEN (operands[0], 0); > > rtx tmp = XVECEXP (operands[0], 0, len - 1); > > - if (XEXP (tmp, 0) != frame_pointer_rtx) > > + if (XEXP (tmp, 0) != hard_frame_pointer_rtx) > > { > > operands[3] = XEXP (tmp, 0); > > gcc_assert (INTVAL (operands[1]) == INTVAL (operands[2])); > > -- > > 2.20.1 > >
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c index 62f435b0a1d..9938a774d91 100644 --- a/gcc/config/arc/arc.c +++ b/gcc/config/arc/arc.c @@ -1651,7 +1651,8 @@ static unsigned int arc_hard_regno_modes[] = { V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, - S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES + S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, + S_MODES, S_MODES }; static unsigned int arc_mode_class [NUM_MACHINE_MODES]; @@ -1886,7 +1887,8 @@ arc_conditional_register_usage (void) /* Handle Special Registers. */ arc_regno_reg_class[CC_REG] = NO_REGS; /* CC_REG: must be NO_REGS. */ - arc_regno_reg_class[62] = GENERAL_REGS; + arc_regno_reg_class[FRAME_POINTER_REGNUM] = GENERAL_REGS; + arc_regno_reg_class[ARG_POINTER_REGNUM] = GENERAL_REGS; if (TARGET_DPFP) for (i = R40_REG; i < R44_REG; ++i) @@ -2616,8 +2618,53 @@ arc_compute_function_type (struct function *fun) return fun->machine->fn_type = fn_type; } -#define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM)) -#define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM)) +/* Helper function to wrap FRAME_POINTER_NEEDED. We do this as + FRAME_POINTER_NEEDED will not be true until the IRA (Integrated + Register Allocator) pass, while we want to get the frame size + correct earlier than the IRA pass. + + When a function uses eh_return we must ensure that the fp register + is saved and then restored so that the unwinder can restore the + correct value for the frame we are going to jump to. + + To do this we force all frames that call eh_return to require a + frame pointer (see arc_frame_pointer_required), this + will ensure that the previous frame pointer is stored on entry to + the function, and will then be reloaded at function exit. + + As the frame pointer is handled as a special case in our prologue + and epilogue code it must not be saved and restored using the + MUST_SAVE_REGISTER mechanism otherwise we run into issues where GCC + believes that the function is not using a frame pointer and that + the value in the fp register is the frame pointer, while the + prologue and epilogue are busy saving and restoring the fp + register. + + During compilation of a function the frame size is evaluated + multiple times, it is not until the reload pass is complete the the + frame size is considered fixed (it is at this point that space for + all spills has been allocated). However the frame_pointer_needed + variable is not set true until the register allocation pass, as a + result in the early stages the frame size does not include space + for the frame pointer to be spilled. + + The problem that this causes is that the rtl generated for + EH_RETURN_HANDLER_RTX uses the details of the frame size to compute + the offset from the frame pointer at which the return address + lives. However, in early passes GCC has not yet realised we need a + frame pointer, and so has not included space for the frame pointer + in the frame size, and so gets the offset of the return address + wrong. This should not be an issue as in later passes GCC has + realised that the frame pointer needs to be spilled, and has + increased the frame size. However, the rtl for the + EH_RETURN_HANDLER_RTX is not regenerated to use the newer, larger + offset, and the wrong smaller offset is used. */ + +static bool +arc_frame_pointer_needed (void) +{ + return (frame_pointer_needed || crtl->calls_eh_return); +} /* Tell prologue and epilogue if register REGNO should be saved / restored. The return address and frame pointer are treated separately. @@ -2656,16 +2703,28 @@ arc_must_save_register (int regno, struct function *func) break; } - if ((regno) != RETURN_ADDR_REGNUM - && (regno) != FRAME_POINTER_REGNUM - && (regno) != STACK_POINTER_REGNUM - && df_regs_ever_live_p (regno) - && (!call_used_regs[regno] - || ARC_INTERRUPT_P (fn_type)) - /* Do not emit code for auto saved regs. */ - && !irq_auto_save_p - && !firq_auto_save_p) - return true; + switch (regno) + { + case RETURN_ADDR_REGNUM: + case STACK_POINTER_REGNUM: + return false; + + case HARD_FRAME_POINTER_REGNUM: + /* If we need FP reg as a frame pointer then don't save it as a + regular reg. */ + if (arc_frame_pointer_needed ()) + return false; + + /* FALLTHRU */ + default: + if (df_regs_ever_live_p (regno) + && (!call_used_regs[regno] + || ARC_INTERRUPT_P (fn_type)) + /* Do not emit code for auto saved regs. */ + && !irq_auto_save_p + && !firq_auto_save_p) + return true; + } return false; } @@ -2682,54 +2741,6 @@ arc_must_save_return_addr (struct function *func) return false; } -/* Helper function to wrap FRAME_POINTER_NEEDED. We do this as - FRAME_POINTER_NEEDED will not be true until the IRA (Integrated - Register Allocator) pass, while we want to get the frame size - correct earlier than the IRA pass. - - When a function uses eh_return we must ensure that the fp register - is saved and then restored so that the unwinder can restore the - correct value for the frame we are going to jump to. - - To do this we force all frames that call eh_return to require a - frame pointer (see arc_frame_pointer_required), this - will ensure that the previous frame pointer is stored on entry to - the function, and will then be reloaded at function exit. - - As the frame pointer is handled as a special case in our prologue - and epilogue code it must not be saved and restored using the - MUST_SAVE_REGISTER mechanism otherwise we run into issues where GCC - believes that the function is not using a frame pointer and that - the value in the fp register is the frame pointer, while the - prologue and epilogue are busy saving and restoring the fp - register. - - During compilation of a function the frame size is evaluated - multiple times, it is not until the reload pass is complete the the - frame size is considered fixed (it is at this point that space for - all spills has been allocated). However the frame_pointer_needed - variable is not set true until the register allocation pass, as a - result in the early stages the frame size does not include space - for the frame pointer to be spilled. - - The problem that this causes is that the rtl generated for - EH_RETURN_HANDLER_RTX uses the details of the frame size to compute - the offset from the frame pointer at which the return address - lives. However, in early passes GCC has not yet realised we need a - frame pointer, and so has not included space for the frame pointer - in the frame size, and so gets the offset of the return address - wrong. This should not be an issue as in later passes GCC has - realised that the frame pointer needs to be spilled, and has - increased the frame size. However, the rtl for the - EH_RETURN_HANDLER_RTX is not regenerated to use the newer, larger - offset, and the wrong smaller offset is used. */ - -static bool -arc_frame_pointer_needed (void) -{ - return (frame_pointer_needed || crtl->calls_eh_return); -} - /* Return non-zero if there are registers to be saved or loaded using millicode thunks. We can only use consecutive sequences starting with r13, and not going beyond r25. @@ -2991,7 +3002,7 @@ frame_restore_reg (rtx reg, HOST_WIDE_INT offset) insn = frame_move_inc (reg, addr, stack_pointer_rtx, 0); add_reg_note (insn, REG_CFA_RESTORE, reg); - if (reg == frame_pointer_rtx) + if (reg == hard_frame_pointer_rtx) add_reg_note (insn, REG_CFA_DEF_CFA, plus_constant (Pmode, stack_pointer_rtx, GET_MODE_SIZE (GET_MODE (reg)) + offset)); @@ -3077,13 +3088,13 @@ arc_save_callee_saves (unsigned int gmask, registers are saved. */ if (save_fp) { - frame_allocated += frame_save_reg (frame_pointer_rtx, offset); + frame_allocated += frame_save_reg (hard_frame_pointer_rtx, offset); offset = 0; } /* Emit mov fp,sp. */ if (arc_frame_pointer_needed ()) - frame_move (frame_pointer_rtx, stack_pointer_rtx); + frame_move (hard_frame_pointer_rtx, stack_pointer_rtx); return frame_allocated; } @@ -3106,7 +3117,7 @@ arc_restore_callee_saves (unsigned int gmask, /* Emit mov fp,sp. */ if (arc_frame_pointer_needed () && offset) { - frame_move (stack_pointer_rtx, frame_pointer_rtx); + frame_move (stack_pointer_rtx, hard_frame_pointer_rtx); frame_deallocated += offset; offset = 0; } @@ -3115,7 +3126,7 @@ arc_restore_callee_saves (unsigned int gmask, { /* Any offset is taken care by previous if-statement. */ gcc_assert (offset == 0); - frame_deallocated += frame_restore_reg (frame_pointer_rtx, 0); + frame_deallocated += frame_restore_reg (hard_frame_pointer_rtx, 0); } if (offset) @@ -3260,11 +3271,11 @@ arc_save_callee_enter (unsigned int gmask, mem = gen_frame_mem (Pmode, plus_constant (Pmode, stack_pointer_rtx, off)); - XVECEXP (insn, 0, indx) = gen_rtx_SET (mem, frame_pointer_rtx); + XVECEXP (insn, 0, indx) = gen_rtx_SET (mem, hard_frame_pointer_rtx); RTX_FRAME_RELATED_P (XVECEXP (insn, 0, indx++)) = 1; off -= UNITS_PER_WORD; - XVECEXP (insn, 0, indx) = gen_rtx_SET (frame_pointer_rtx, + XVECEXP (insn, 0, indx) = gen_rtx_SET (hard_frame_pointer_rtx, stack_pointer_rtx); RTX_FRAME_RELATED_P (XVECEXP (insn, 0, indx++)) = 1; save_fp = false; @@ -3368,7 +3379,7 @@ arc_restore_callee_leave (unsigned int gmask, mem = gen_frame_mem (Pmode, plus_constant (Pmode, stack_pointer_rtx, off)); - XVECEXP (insn, 0, indx) = gen_rtx_SET (frame_pointer_rtx, mem); + XVECEXP (insn, 0, indx) = gen_rtx_SET (hard_frame_pointer_rtx, mem); RTX_FRAME_RELATED_P (XVECEXP (insn, 0, indx++)) = 1; off -= UNITS_PER_WORD; } @@ -3387,7 +3398,7 @@ arc_restore_callee_leave (unsigned int gmask, /* Dwarf related info. */ if (restore_fp) { - add_reg_note (insn, REG_CFA_RESTORE, frame_pointer_rtx); + add_reg_note (insn, REG_CFA_RESTORE, hard_frame_pointer_rtx); add_reg_note (insn, REG_CFA_DEF_CFA, plus_constant (Pmode, stack_pointer_rtx, offset + nregs * UNITS_PER_WORD)); @@ -3525,11 +3536,11 @@ arc_save_callee_milli (unsigned int gmask, above loop to save fp because our ABI states fp goes aftert all registers are saved. */ if (save_fp) - frame_allocated += frame_save_reg (frame_pointer_rtx, offset); + frame_allocated += frame_save_reg (hard_frame_pointer_rtx, offset); /* Emit mov fp,sp. */ if (arc_frame_pointer_needed ()) - frame_move (frame_pointer_rtx, stack_pointer_rtx); + frame_move (hard_frame_pointer_rtx, stack_pointer_rtx); return frame_allocated; } @@ -3559,13 +3570,13 @@ arc_restore_callee_milli (unsigned int gmask, /* Emit mov fp,sp. */ if (arc_frame_pointer_needed () && offset) { - frame_move (stack_pointer_rtx, frame_pointer_rtx); + frame_move (stack_pointer_rtx, hard_frame_pointer_rtx); frame_allocated = offset; offset = 0; } if (restore_fp) - frame_allocated += frame_restore_reg (frame_pointer_rtx, 0); + frame_allocated += frame_restore_reg (hard_frame_pointer_rtx, 0); if (offset) { @@ -3875,7 +3886,7 @@ arc_check_multi (rtx op, bool push_p) if (REGNO (reg) == RETURN_ADDR_REGNUM && i == start) regno = 12; - else if (REGNO (reg) == FRAME_POINTER_REGNUM) + else if (REGNO (reg) == HARD_FRAME_POINTER_REGNUM) ++i; else if (REGNO (reg) != regno) return false; @@ -3922,7 +3933,7 @@ arc_eh_return_address_location (rtx source) included in the 'extra_size' field. */ offset = afi->reg_size + afi->extra_size - 4; mem = gen_frame_mem (Pmode, - plus_constant (Pmode, frame_pointer_rtx, offset)); + plus_constant (Pmode, hard_frame_pointer_rtx, offset)); /* The following should not be needed, and is, really a hack. The issue being worked around here is that the DSE (Dead Store @@ -5396,7 +5407,7 @@ arc_final_prescan_insn (rtx_insn *insn, rtx *opvec ATTRIBUTE_UNUSED, static bool arc_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to) { - return ((to == FRAME_POINTER_REGNUM) || !arc_frame_pointer_needed ()); + return ((to == HARD_FRAME_POINTER_REGNUM) || (to == STACK_POINTER_REGNUM)); } /* Define the offset between two registers, one to be eliminated, and @@ -5408,7 +5419,7 @@ arc_initial_elimination_offset (int from, int to) if (!cfun->machine->frame_info.initialized) arc_compute_frame_size (); - if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM) + if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM) { return (cfun->machine->frame_info.extra_size + cfun->machine->frame_info.reg_size); @@ -5427,6 +5438,8 @@ arc_initial_elimination_offset (int from, int to) + cfun->machine->frame_info.extra_size + cfun->machine->frame_info.reg_size)); } + if ((from == FRAME_POINTER_REGNUM) && (to == HARD_FRAME_POINTER_REGNUM)) + return 0; gcc_unreachable (); } @@ -11024,7 +11037,7 @@ arc_builtin_setjmp_frame_value (void) frame pointer value for this frame (if the use of the frame pointer had not been removed). We really do want the raw frame pointer register value. */ - return gen_raw_REG (Pmode, FRAME_POINTER_REGNUM); + return gen_raw_REG (Pmode, HARD_FRAME_POINTER_REGNUM); } /* Return nonzero if a jli call should be generated for a call from diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h index 6a77869b58c..fbe71278346 100644 --- a/gcc/config/arc/arc.h +++ b/gcc/config/arc/arc.h @@ -325,7 +325,7 @@ if (GET_MODE_CLASS (MODE) == MODE_INT \ argument pointer. */ /* r63 is pc, r64-r127 = simd vregs, r128-r143 = simd dma config regs - r144, r145 = lp_start, lp_end + r144, r145 = ARG_POINTER, FRAME_POINTER and therefore the pseudo registers start from r146. */ #define FIRST_PSEUDO_REGISTER 146 @@ -366,7 +366,7 @@ if (GET_MODE_CLASS (MODE) == MODE_INT \ { 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 1, 1, 1, 1, 1, 1, \ + 0, 0, 1, 0, 1, 1, 1, 1, \ \ 1, 1, 1, 1, 1, 1, 1, 1, \ 0, 0, 0, 0, 1, 1, 1, 1, \ @@ -398,7 +398,7 @@ if (GET_MODE_CLASS (MODE) == MODE_INT \ 1, 1, 1, 1, 1, 1, 1, 1, \ 1, 1, 1, 1, 1, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 1, 1, 1, 1, 1, 1, \ + 0, 0, 1, 0, 1, 1, 1, 1, \ \ 1, 1, 1, 1, 1, 1, 1, 1, \ 1, 1, 1, 1, 1, 1, 1, 1, \ @@ -511,10 +511,10 @@ enum reg_class {0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'Rsd'. */ \ {0x0000000f, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'Rcd'. */ \ {0x0000f00f, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'q'. */ \ - {0x1c001fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'Rsc'. */ \ + {0x00001fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'Rsc'. */ \ {0x9fffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'h'. */ \ {0x00000000, 0x00000f00, 0x00000000, 0x00000000, 0x00000000}, /* 'D'. */ \ - {0xffffffff, 0x8fffffff, 0x00000000, 0x00000000, 0x00000000}, /* 'r'. */ \ + {0xffffffff, 0x8fffffff, 0x00000000, 0x00000000, 0x00030000}, /* 'r'. */ \ {0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000}, /* 'v'. */ \ {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff}, /* 'd'. */ \ {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0003ffff} /* ALL_REGS. */\ @@ -562,11 +562,14 @@ extern enum reg_class arc_regno_reg_class[]; Since they use reg_renumber, they are safe only once reg_renumber has been allocated, which happens in local-alloc.c. */ #define REGNO_OK_FOR_BASE_P(REGNO) \ - ((REGNO) < 29 || ((REGNO) == ARG_POINTER_REGNUM) || ((REGNO) == 63) \ + ((REGNO) < 29 \ + || ((REGNO) == ARG_POINTER_REGNUM) \ + || ((REGNO) == FRAME_POINTER_REGNUM) \ + || ((REGNO) == PCL_REG) \ || ((unsigned) reg_renumber[REGNO] < 29) \ || ((unsigned) (REGNO) == (unsigned) arc_tp_regno) \ || (fixed_regs[REGNO] == 0 && IN_RANGE (REGNO, 32, 59)) \ - || ((REGNO) == 30 && fixed_regs[REGNO] == 0)) + || (fixed_regs[REGNO] == 0 && (REGNO) == R30_REG)) #define REGNO_OK_FOR_INDEX_P(REGNO) REGNO_OK_FOR_BASE_P(REGNO) @@ -652,11 +655,12 @@ arc_return_addr_rtx(COUNT,FRAME) #define STACK_POINTER_REGNUM 28 /* Base register for access to local variables of the function. */ -#define FRAME_POINTER_REGNUM 27 +#define FRAME_POINTER_REGNUM 145 +#define HARD_FRAME_POINTER_REGNUM 27 /* Base register for access to arguments of the function. This register will be eliminated into either fp or sp. */ -#define ARG_POINTER_REGNUM 62 +#define ARG_POINTER_REGNUM 144 #define RETURN_ADDR_REGNUM 31 @@ -766,8 +770,9 @@ arc_return_addr_rtx(COUNT,FRAME) #define ELIMINABLE_REGS \ {{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ - {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ - {FRAME_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 the offset between two registers, one to be eliminated, and the other its replacement, at the start of a routine. */ @@ -1161,7 +1166,7 @@ extern char rname56[], rname57[], rname58[], rname59[]; "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39", \ "d1", "d1", "d2", "d2", "r44", "r45", "r46", "r47", \ "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55", \ - rname56,rname57,rname58,rname59,"lp_count", "cc", "ap", "pcl", \ + rname56,rname57,rname58,rname59,"lp_count", "cc", "limm", "pcl", \ "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7", \ "vr8", "vr9", "vr10", "vr11", "vr12", "vr13", "vr14", "vr15", \ "vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23", \ @@ -1172,7 +1177,7 @@ extern char rname56[], rname57[], rname58[], rname59[]; "vr56", "vr57", "vr58", "vr59", "vr60", "vr61", "vr62", "vr63", \ "dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7", \ "dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7", \ - "lp_start", "lp_end" \ + "arg", "frame" \ } #define ADDITIONAL_REGISTER_NAMES \ diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md index 3a903d4224a..7ac5a1b5785 100644 --- a/gcc/config/arc/arc.md +++ b/gcc/config/arc/arc.md @@ -202,8 +202,6 @@ (LP_COUNT 60) (CC_REG 61) (PCL_REG 63) - (LP_START 144) - (LP_END 145) ] ) @@ -3467,8 +3465,6 @@ core_3, archs4x, archs4xd, archs4xd_slow" (match_operand:SI 2 "nonmemory_operand" "rn,Cal")])) (clobber (match_scratch:SI 4 "=X,X")) (clobber (reg:SI LP_COUNT)) - (clobber (reg:SI LP_START)) - (clobber (reg:SI LP_END)) (clobber (reg:CC CC_REG)) ] "!TARGET_BARREL_SHIFTER" @@ -6508,7 +6504,7 @@ core_3, archs4x, archs4xd, archs4xd_slow" { int len = XVECLEN (operands[0], 0); rtx tmp = XVECEXP (operands[0], 0, len - 1); - if (XEXP (tmp, 0) != frame_pointer_rtx) + if (XEXP (tmp, 0) != hard_frame_pointer_rtx) { operands[3] = XEXP (tmp, 0); gcc_assert (INTVAL (operands[1]) == INTVAL (operands[2])); @@ -6538,7 +6534,7 @@ core_3, archs4x, archs4xd, archs4xd_slow" { int len = XVECLEN (operands[0], 0); rtx tmp = XVECEXP (operands[0], 0, len - 1); - if (XEXP (tmp, 0) != frame_pointer_rtx) + if (XEXP (tmp, 0) != hard_frame_pointer_rtx) { operands[3] = XEXP (tmp, 0); gcc_assert (INTVAL (operands[1]) == INTVAL (operands[2])); @@ -6569,7 +6565,7 @@ core_3, archs4x, archs4xd, archs4xd_slow" { int len = XVECLEN (operands[0], 0); rtx tmp = XVECEXP (operands[0], 0, len - 1); - if (XEXP (tmp, 0) != frame_pointer_rtx) + if (XEXP (tmp, 0) != hard_frame_pointer_rtx) { operands[3] = XEXP (tmp, 0); gcc_assert (INTVAL (operands[1]) == INTVAL (operands[2])); @@ -6600,7 +6596,7 @@ core_3, archs4x, archs4xd, archs4xd_slow" { int len = XVECLEN (operands[0], 0); rtx tmp = XVECEXP (operands[0], 0, len - 1); - if (XEXP (tmp, 0) != frame_pointer_rtx) + if (XEXP (tmp, 0) != hard_frame_pointer_rtx) { operands[3] = XEXP (tmp, 0); gcc_assert (INTVAL (operands[1]) == INTVAL (operands[2]));