summaryrefslogtreecommitdiff
path: root/gcc/config/cris
diff options
context:
space:
mode:
authorHans-Peter Nilsson <hp@axis.com>2021-03-11 03:38:34 +0100
committerHans-Peter Nilsson <hp@axis.com>2021-03-11 03:43:48 +0100
commitaa27696b798b34730f5266cac2adba9178ebc3ae (patch)
treec31b33844b404d76ff180b28c60c192c48c1a3eb /gcc/config/cris
parente9800852067503ed0fe4efbfcac5f172b8596ee6 (diff)
downloadgcc-aa27696b798b34730f5266cac2adba9178ebc3ae.tar.gz
cris: define HARD_FRAME_POINTER_REGNUM
Beware, tm.texi doesn't tell the whole story: a defined HARD_FRAME_POINTER_REGNUM (different to FRAME_POINTER_REGNUM) is supposed to make work easier for reload, being able to easily tell actual frame-pointer-related addresses from those that happen to use the same register or something to that effect. On reasonable code the performance effect is barely measurable. Looking at libgcc changes for -march=v10, the effect (where noticeable) is mostly indeterminate churn. Instances where it's not just insns moved around at no obvious effect: one more insn for addvdi3, subvdi3; two insns more in floatdisf; three insns shorter fixunsdfdi. Some of those seem related to pairing r8 with r9. The only effect on coremark is an infinitesimal positive effect from a three(!) cycles total (from the 15 calls) faster execution paths in vfprintf_r. Local microbenchmarks give similar results. With that in mind and not forgetting that expectations in the register allocator and reload leaning towards HARD_FRAME_POINTER_REGNUM defined (and different to) FRAME_POINTER_REGNUM or to wit, "all the kids do it", why not. Note that the offset at elimination really is 0. gcc: * config/cris/cris.h (HARD_FRAME_POINTER_REGNUM): Define. Change FRAME_POINTER_REGNUM to correspond to a new faked register faked_fp, part of GENNONACR_REGS like faked_ap. (CRIS_FAKED_REGS_CONTENTS): New helper macro. (FIRST_PSEUDO_REGISTER, FIXED_REGISTERS, CALL_USED_REGISTERS): (REG_ALLOC_ORDER, REG_CLASS_CONTENTS, REGNO_OK_FOR_BASE_P) (ELIMINABLE_REGS, REGISTER_NAMES): Adjust accordingly. * config/cris/cris.md (CRIS_FP_REGNUM): Renumber to new faked register. (CRIS_REAL_FP_REGNUM): New constant. * config/cris/cris.c (cris_reg_saved_in_regsave_area): Check for HARD_FRAME_POINTER_REGNUM instead of FRAME_POINTER_REGNUM. (cris_initial_elimination_offset): Handle elimination changes to HARD_FRAME_POINTER_REGNUM instead of FRAME_POINTER_REGNUM and add one from FRAME_POINTER_REGNUM to HARD_FRAME_POINTER_REGNUM. (cris_expand_prologue, cris_expand_epilogue): Emit code for hard_frame_pointer_rtx instead of frame_pointer_rtx.
Diffstat (limited to 'gcc/config/cris')
-rw-r--r--gcc/config/cris/cris.c16
-rw-r--r--gcc/config/cris/cris.h35
-rw-r--r--gcc/config/cris/cris.md5
3 files changed, 36 insertions, 20 deletions
diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c
index 42f0a529f65..d9213d7ffb6 100644
--- a/gcc/config/cris/cris.c
+++ b/gcc/config/cris/cris.c
@@ -864,7 +864,7 @@ cris_reg_saved_in_regsave_area (unsigned int regno)
return
(((df_regs_ever_live_p (regno)
&& !call_used_or_fixed_reg_p (regno)))
- && (regno != FRAME_POINTER_REGNUM || !frame_pointer_needed)
+ && (regno != HARD_FRAME_POINTER_REGNUM || !frame_pointer_needed)
&& regno != CRIS_SRP_REGNUM)
|| (crtl->calls_eh_return
&& (regno == EH_RETURN_DATA_REGNO (0)
@@ -1445,7 +1445,7 @@ cris_initial_elimination_offset (int fromreg, int toreg)
int ap_fp_offset = 4 + (return_address_on_stack ? 4 : 0);
if (fromreg == ARG_POINTER_REGNUM
- && toreg == FRAME_POINTER_REGNUM)
+ && toreg == HARD_FRAME_POINTER_REGNUM)
return ap_fp_offset;
/* Between the frame pointer and the stack are only "normal" stack
@@ -1459,6 +1459,10 @@ cris_initial_elimination_offset (int fromreg, int toreg)
&& toreg == STACK_POINTER_REGNUM)
return ap_fp_offset + fp_sp_offset - 4;
+ if (fromreg == FRAME_POINTER_REGNUM
+ && toreg == HARD_FRAME_POINTER_REGNUM)
+ return 0;
+
gcc_unreachable ();
}
@@ -2749,10 +2753,10 @@ cris_expand_prologue (void)
mem = gen_rtx_MEM (SImode, stack_pointer_rtx);
set_mem_alias_set (mem, get_frame_alias_set ());
- insn = emit_move_insn (mem, frame_pointer_rtx);
+ insn = emit_move_insn (mem, hard_frame_pointer_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
- 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;
framesize += 4;
@@ -3015,11 +3019,11 @@ cris_expand_epilogue (void)
emit_insn (gen_cris_frame_deallocated_barrier ());
- emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
+ emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx);
mem = gen_rtx_MEM (SImode, gen_rtx_POST_INC (SImode,
stack_pointer_rtx));
set_mem_alias_set (mem, get_frame_alias_set ());
- insn = emit_move_insn (frame_pointer_rtx, mem);
+ insn = emit_move_insn (hard_frame_pointer_rtx, mem);
/* Whenever we emit insns with post-incremented addresses
ourselves, we must add a post-inc note manually. */
diff --git a/gcc/config/cris/cris.h b/gcc/config/cris/cris.h
index 4d04ef869f3..1ab830e4d75 100644
--- a/gcc/config/cris/cris.h
+++ b/gcc/config/cris/cris.h
@@ -373,8 +373,8 @@ extern int cris_cpu_version;
/* Node: Register Basics */
/* We count all 16 non-special registers, SRP, a faked argument
- pointer register, MOF and CCR/DCCR. */
-#define FIRST_PSEUDO_REGISTER (16 + 1 + 1 + 1 + 1)
+ pointer register, MOF, CCR/DCCR, and the faked frame-pointer. */
+#define FIRST_PSEUDO_REGISTER (16 + 1 + 1 + 1 + 1 + 1)
/* For CRIS, these are r15 (pc) and r14 (sp). Register r8 is used as a
frame-pointer, but is not fixed. SRP is not included in general
@@ -382,12 +382,12 @@ extern int cris_cpu_version;
registers are fixed at the moment. The faked argument pointer register
is fixed too. */
#define FIXED_REGISTERS \
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1}
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1}
/* Register r9 is used for structure-address, r10-r13 for parameters,
r10- for return values. */
#define CALL_USED_REGISTERS \
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1}
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1}
/* Node: Allocation Order */
@@ -410,7 +410,8 @@ extern int cris_cpu_version;
Use struct-return address first, since very few functions use
structure return values so it is likely to be available. */
#define REG_ALLOC_ORDER \
- {9, 13, 12, 11, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 14, 15, 17, 16, 18, 19}
+ {9, 13, 12, 11, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 14, 15, 17, 16, 18, 19, \
+ 20}
/* Node: Leaf Functions */
@@ -451,6 +452,9 @@ enum reg_class
#define CRIS_SPECIAL_REGS_CONTENTS \
((1 << CRIS_SRP_REGNUM) | (1 << CRIS_MOF_REGNUM) | (1 << CRIS_CC0_REGNUM))
+#define CRIS_FAKED_REGS_CONTENTS \
+ ((1 << CRIS_AP_REGNUM) | (1 << CRIS_FP_REGNUM))
+
/* Count in the faked argument register in GENERAL_REGS. Keep out SRP. */
#define REG_CLASS_CONTENTS \
{ \
@@ -464,13 +468,13 @@ enum reg_class
{CRIS_SPECIAL_REGS_CONTENTS}, \
{CRIS_SPECIAL_REGS_CONTENTS \
| (1 << CRIS_ACR_REGNUM)}, \
- {(0xffff | (1 << CRIS_AP_REGNUM)) \
+ {(0xffff | CRIS_FAKED_REGS_CONTENTS) \
& ~(1 << CRIS_ACR_REGNUM)}, \
- {(0xffff | (1 << CRIS_AP_REGNUM) \
+ {(0xffff | CRIS_FAKED_REGS_CONTENTS \
| CRIS_SPECIAL_REGS_CONTENTS) \
& ~(1 << CRIS_ACR_REGNUM)}, \
- {0xffff | (1 << CRIS_AP_REGNUM)}, \
- {0xffff | (1 << CRIS_AP_REGNUM) \
+ {0xffff | CRIS_FAKED_REGS_CONTENTS}, \
+ {0xffff | CRIS_FAKED_REGS_CONTENTS \
| CRIS_SPECIAL_REGS_CONTENTS} \
}
@@ -493,8 +497,10 @@ enum reg_class
allocation. */
#define REGNO_OK_FOR_BASE_P(REGNO) \
((REGNO) <= CRIS_LAST_GENERAL_REGISTER \
+ || (REGNO) == FRAME_POINTER_REGNUM \
|| (REGNO) == ARG_POINTER_REGNUM \
|| (unsigned) reg_renumber[REGNO] <= CRIS_LAST_GENERAL_REGISTER \
+ || (unsigned) reg_renumber[REGNO] == FRAME_POINTER_REGNUM \
|| (unsigned) reg_renumber[REGNO] == ARG_POINTER_REGNUM)
/* See REGNO_OK_FOR_BASE_P. */
@@ -580,6 +586,9 @@ enum reg_class
/* Register used for frame pointer. This is also the last of the saved
registers, when a frame pointer is not used. */
+#define HARD_FRAME_POINTER_REGNUM CRIS_REAL_FP_REGNUM
+
+/* Faked register, is always eliminated to at least CRIS_REAL_FP_REGNUM. */
#define FRAME_POINTER_REGNUM CRIS_FP_REGNUM
/* Faked register, is always eliminated. We need it to eliminate
@@ -596,8 +605,9 @@ enum reg_class
#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 INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
(OFFSET) = cris_initial_elimination_offset (FROM, TO)
@@ -818,7 +828,8 @@ struct cum_args {int regs;};
#define REGISTER_NAMES \
{"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", \
- "r9", "r10", "r11", "r12", "r13", "sp", "pc", "srp", "mof", "faked_ap", "dccr"}
+ "r9", "r10", "r11", "r12", "r13", "sp", "pc", "srp", \
+ "mof", "faked_ap", "dccr", "faked_fp"}
#define ADDITIONAL_REGISTER_NAMES \
{{"r14", 14}, {"r15", 15}}
diff --git a/gcc/config/cris/cris.md b/gcc/config/cris/cris.md
index 069f7e00b6d..7de0ec63fcf 100644
--- a/gcc/config/cris/cris.md
+++ b/gcc/config/cris/cris.md
@@ -58,13 +58,14 @@
;; Register numbers.
(define_constants
[(CRIS_STATIC_CHAIN_REGNUM 7)
- (CRIS_FP_REGNUM 8)
+ (CRIS_REAL_FP_REGNUM 8)
(CRIS_SP_REGNUM 14)
(CRIS_ACR_REGNUM 15)
(CRIS_SRP_REGNUM 16)
(CRIS_MOF_REGNUM 17)
(CRIS_AP_REGNUM 18)
- (CRIS_CC0_REGNUM 19)]
+ (CRIS_CC0_REGNUM 19)
+ (CRIS_FP_REGNUM 20)]
)
;; We need an attribute to define whether an instruction can be put in