This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Patch Fix PR32871 -- [avr] gcc is pushing too many registers


The attached patch fixs:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=32871

Although the bug is against the AVR target it reveals a weakness in using df_regs_ever_live_p.
to determine register to save and restore that may apply to other targets.


The fix determines which registers are used as arguments to function using
INIT_CUMULATIVE_ARGS, FUNCTION_ARG and FUNCTION_ARG_ADVANCE
(This is patch is thus relatively portable for other targets)

The argument registers are then omitted from epilog/prolog save and restores
(as all argument registers are assumed clobbered.)


Tested against HEAD and had no new regression for torture/execute testsuite.
Please review with the intention of committing this chnage for avr target.


2000-03-02 Andrew Hutchinson <hutchinsonandy@aim.com>


   PR target/32871
   * config/avr/avr.c (avr_args): Add new function to set argument
   registers in bitmap.
   (avr_regs_to_save): Don't mark argument registers for saving.
   (sequent_regs_live): Add bitmap argument. Use bitmap to determine
   sequence of registers.
   (expand_prologue): Pass bitmap of registers for sequence.
   (expand_epilogue): Pass bitmap of registers for sequence.
Index: avr.c
===================================================================
--- avr.c   (revision 132824)
+++ avr.c   (working copy)
@@ -53,7 +53,8 @@
 static int signal_function_p (tree);
 static int avr_OS_task_function_p (tree);
 static int avr_regs_to_save (HARD_REG_SET *);
-static int sequent_regs_live (void);
+static void avr_args (HARD_REG_SET *);
+static int sequent_regs_live (HARD_REG_SET *);
 static const char *ptrreg_to_str (int);
 static const char *cond_string (enum rtx_code);
 static int avr_num_arg_regs (enum machine_mode, tree);
@@ -469,7 +470,9 @@
   int int_or_sig_p = (interrupt_function_p (current_function_decl)
              || signal_function_p (current_function_decl));
   int leaf_func_p = leaf_function_p ();
-
+  HARD_REG_SET args;
+  CLEAR_HARD_REG_SET (args);
+  avr_args (&args);
   if (set)
     CLEAR_HARD_REG_SET (*set);
   count = 0;
@@ -489,6 +492,7 @@
 
       if ((int_or_sig_p && !leaf_func_p && call_used_regs[reg])
      || (df_regs_ever_live_p (reg)
+         && !TEST_HARD_REG_BIT (args, reg)
          && (int_or_sig_p || !call_used_regs[reg])
          && !(frame_pointer_needed
           && (reg == REG_Y || reg == (REG_Y+1)))))
@@ -534,7 +538,7 @@
 /* This function checks sequence of live registers.  */
 
 static int
-sequent_regs_live (void)
+sequent_regs_live (HARD_REG_SET *set)
 {
   int reg;
   int live_seq=0;
@@ -542,9 +546,7 @@
 
   for (reg = 0; reg < 18; ++reg)
     {
-      if (!call_used_regs[reg])
-   {
-     if (df_regs_ever_live_p (reg))
+     if (TEST_HARD_REG_BIT(*set, reg))
        {
          ++live_seq;
          ++cur_seq;
@@ -552,7 +554,6 @@
      else
        cur_seq = 0;
    }
-    }
 
   if (!frame_pointer_needed)
     {
@@ -611,7 +612,8 @@
     }
 
   avr_regs_to_save (&set);
-  live_seq = sequent_regs_live ();
+  live_seq = sequent_regs_live (&set);
+  
   minimize = (TARGET_CALL_PROLOGUES
          && !cfun->machine->is_interrupt
          && !cfun->machine->is_signal
@@ -834,7 +836,8 @@
     }
 
   avr_regs_to_save (&set);
-  live_seq = sequent_regs_live ();
+  live_seq = sequent_regs_live (&set);
+  
   minimize = (TARGET_CALL_PROLOGUES
          && !cfun->machine->is_interrupt
          && !cfun->machine->is_signal
@@ -1479,6 +1482,43 @@
   return (r >= 8 && r <= 25);
 }
 
+/* Modify HARD_REG_SET. Set bit if registers are used for arguments */
+
+static void
+avr_args (HARD_REG_SET *set)
+{
+    int reg;
+    int i;
+    rtx arg;
+    CUMULATIVE_ARGS cum;
+
+    tree decl = DECL_ARGUMENTS (current_function_decl);
+    INIT_CUMULATIVE_ARGS (cum, TREE_TYPE (current_function_decl), NULL_RTX, decl, -1);
+    /* go through all arguments */
+    for (; decl; decl = TREE_CHAIN (decl))
+    {
+        if ( TREE_CODE (decl) == PARM_DECL
+        && DECL_NAME (decl) && !DECL_ARTIFICIAL (decl))  
+       {   
+           enum machine_mode mode = DECL_MODE (decl);
+            /* Get argument RTX and look for register */
+            /* Note: This target does not use named arg */
+            arg = FUNCTION_ARG (cum, mode, DECL_ARG_TYPE (decl), 1);   
+            FUNCTION_ARG_ADVANCE (cum, mode, DECL_ARG_TYPE (decl), 1);;       
+            if (arg && REG_P (arg))
+            {   
+                reg = REGNO (arg);
+               /* Set all registers used by arguments size */
+                for (i = 0;i < HARD_REGNO_NREGS (reg, mode);i++)
+                {
+                  if (set)
+                      SET_HARD_REG_BIT (*set, reg + i);  
+                }
+            }
+       }
+    }
+}
+
 /* Initializing the variable cum for the state at the beginning
    of the argument list.  */
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]