]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
cris: define HARD_FRAME_POINTER_REGNUM
authorHans-Peter Nilsson <hp@axis.com>
Thu, 11 Mar 2021 02:38:34 +0000 (03:38 +0100)
committerHans-Peter Nilsson <hp@axis.com>
Thu, 11 Mar 2021 02:43:48 +0000 (03:43 +0100)
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.

gcc/config/cris/cris.c
gcc/config/cris/cris.h
gcc/config/cris/cris.md

index 42f0a529f652fbe153813a90f4eac5ca8ded6afb..d9213d7ffb672bb7394996ccdf44c3812ca3b62a 100644 (file)
@@ -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.  */
index 4d04ef869f3d508b4cfba878ca14fc066cd1a2ff..1ab830e4d750d4b175cf17db6f46fea1b3867636 100644 (file)
@@ -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}}
index 069f7e00b6dbd261485b30599a168d95630fb648..7de0ec63fcf380bf3e59ff48ef107ad9a47538f5 100644 (file)
 ;; 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