Hi Guys,

  I am applying the patch below to enhance the RX backend so that it
  will push and pop multiple groups of registers using the PUSHM and
  POPM instructions, thus reducing code size and increasing
  performance.

Cheers
  Nick

gcc/ChangeLog
2015-05-28  Nick Clifton  <ni...@redhat.com>

        * config/rx/rx.c (push_regs): New function.  Extracts code from...
        (rx_expand_prologue): ... here.  Use push_regs to push even small
        spans of registers.
        (pop_regs): New function.
        (rx_expand_epilogue):  Use pop_regs to pop even small spans of
        registers.

Index: gcc/config/rx/rx.c
===================================================================
--- gcc/config/rx/rx.c  (revision 223737)
+++ gcc/config/rx/rx.c  (working copy)
@@ -1567,6 +1567,10 @@
      has specified --fixed-<reg-name> on the command line and in such
      circumstances we do not want to touch the fixed registers at all.
 
+     Note also that the code in the prologue/epilogue handlers will
+     automatically merge multiple PUSHes of adjacent registers into a single
+     PUSHM.
+
      FIXME: Is it worth improving this heuristic ?  */
   pushed_mask = (-1 << low) & ~(-1 << (high + 1));
   unneeded_pushes = (pushed_mask & (~ save_mask)) & pushed_mask;
@@ -1716,6 +1720,19 @@
   return;
 }
 
+static void
+push_regs (unsigned int high, unsigned int low)
+{
+  rtx insn;
+
+  if (low == high)
+    insn = emit_insn (gen_stack_push (gen_rtx_REG (SImode, low)));
+  else
+    insn = emit_insn (gen_stack_pushm (GEN_INT (((high - low) + 1) * 
UNITS_PER_WORD),
+                                      gen_rx_store_vector (low, high)));
+  mark_frame_related (insn);
+}
+
 void
 rx_expand_prologue (void)
 {
@@ -1725,7 +1742,6 @@
   unsigned int low;
   unsigned int high;
   unsigned int reg;
-  rtx insn;
 
   /* Naked functions use their own, programmer provided prologues.  */
   if (is_naked_func (NULL_TREE))
@@ -1735,7 +1751,7 @@
 
   if (flag_stack_usage_info)
     current_function_static_stack_size = frame_size + stack_size;
-
+  
   /* If we use any of the callee-saved registers, save them now.  */
   if (mask)
     {
@@ -1743,20 +1759,25 @@
       for (reg = CC_REGNUM; reg --;)
        if (mask & (1 << reg))
          {
-           insn = emit_insn (gen_stack_push (gen_rtx_REG (SImode, reg)));
-           mark_frame_related (insn);
+           low = high = reg;
+
+           /* Look for a span of registers.
+              Note - we do not have to worry about -Os and whether
+              it is better to use a single, longer PUSHM as
+              rx_get_stack_layout has already done that for us.  */
+           while (reg-- > 0)
+             if ((mask & (1 << reg)) == 0)
+               break;
+             else
+               --low;
+
+           push_regs (high, low);
+           if (reg == (unsigned) -1)
+             break;
          }
     }
   else if (low)
-    {
-      if (high == low)
-       insn = emit_insn (gen_stack_push (gen_rtx_REG (SImode, low)));
-      else
-       insn = emit_insn (gen_stack_pushm (GEN_INT (((high - low) + 1)
-                                                   * UNITS_PER_WORD),
-                                          gen_rx_store_vector (low, high)));
-      mark_frame_related (insn);
-    }
+    push_regs (high, low);
 
   if (MUST_SAVE_ACC_REGISTER)
     {
@@ -2031,6 +2052,16 @@
          && low == 0);
 }
 
+static void
+pop_regs (unsigned int high, unsigned int low)
+{
+  if (high == low)
+    emit_insn (gen_stack_pop (gen_rtx_REG (SImode, low)));
+  else
+    emit_insn (gen_stack_popm (GEN_INT (((high - low) + 1) * UNITS_PER_WORD),
+                              gen_rx_popm_vector (low, high)));
+}
+
 void
 rx_expand_epilogue (bool is_sibcall)
 {
@@ -2143,16 +2174,16 @@
        {
          for (reg = 0; reg < CC_REGNUM; reg ++)
            if (register_mask & (1 << reg))
-             emit_insn (gen_stack_pop (gen_rtx_REG (SImode, reg)));
+             {
+               low = high = reg;
+               while (register_mask & (1 << high))
+                 high ++;
+               pop_regs (high - 1, low);
+               reg = high;
+             }
        }
       else if (low)
-       {
-         if (high == low)
-           emit_insn (gen_stack_pop (gen_rtx_REG (SImode, low)));
-         else
-           emit_insn (gen_stack_popm (GEN_INT (regs_size),
-                                      gen_rx_popm_vector (low, high)));
-       }
+       pop_regs (high, low);
 
       if (is_fast_interrupt_func (NULL_TREE))
        {

Reply via email to