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] Support multiple registers for the frame pointer


The AMD GCN architecture uses 64-bit pointers, but the scalar registers are 32-bit wide, so pointers must reside in a pair of registers.

The two hard registers holding the frame pointer are currently fixed, but if they are changed to unfixed (so that the FP can be eliminated), GCC would sometimes allocate the second register to a pseudo while the frame pointer was in use, clobbering the value of the FP and crashing the program.

GCC currently does not handle multi-register hard frame pointers properly - no_unit_alloc_regs, regs_ever_live, eliminable_regset and ira_no_alloc_regs (which gets copied to lra_no_alloc_regs) are only set for HARD_FRAME_POINTER_REGNUM and not for any subsequent registers that may be used, which means that the register allocators consider HARD_FRAME_POINTER_REGNUM+1 free. This patch determines the number of registers needed to store the frame pointer using hard_regno_nregs, and sets the required variables for HARD_FRAME_POINTER_REGNUM and however many adjacent registers are needed (which on most architectures should be zero).

Bootstrapped on x86_64 and tested with no regressions, which is not surprising as nothing different happens when the FP fits into a single register. I believe this is true for the 64-bit variants of the more popular architectures as well (ARM, RS6000, MIPS, Sparc). Are there any other architectures similar to GCN (i.e. 64-bit pointers with 32-bit GPRs)?

I have not included any specific testcases for this issue as it can affect pretty much everything not using -fomit-frame-pointer on AMD GCN.

Okay for trunk?

Kwok Yeung


    Add support for using multiple registers to hold the frame pointer

    2019-11-02  Kwok Cheung Yeung  <kcy@codesourcery.com>

    	gcc/
    	* ira.c (setup_alloc_regs): Setup no_unit_alloc_regs for
    	frame pointer in multiple registers.
    	(ira_setup_eliminable_regset): Setup eliminable_regset,
    	ira_no_alloc_regs and regs_ever_live for frame pointer in
    	multiple registers.

diff --git a/gcc/ira.c b/gcc/ira.c
index 9f8da67..25e9359 100644
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -515,7 +515,13 @@ setup_alloc_regs (bool use_hard_frame_p)
 #endif
   no_unit_alloc_regs = fixed_nonglobal_reg_set;
   if (! use_hard_frame_p)
-    SET_HARD_REG_BIT (no_unit_alloc_regs, HARD_FRAME_POINTER_REGNUM);
+    {
+ int fp_reg_count = hard_regno_nregs (HARD_FRAME_POINTER_REGNUM, Pmode);
+      for (int reg = HARD_FRAME_POINTER_REGNUM;
+	   reg < HARD_FRAME_POINTER_REGNUM + fp_reg_count;
+	   reg++)
+	SET_HARD_REG_BIT (no_unit_alloc_regs, reg);
+    }
   setup_class_hard_regs ();
 }

@@ -2248,6 +2254,7 @@ ira_setup_eliminable_regset (void)
 {
   int i;
static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
+  int fp_reg_count = hard_regno_nregs (HARD_FRAME_POINTER_REGNUM, Pmode);

   /* Setup is_leaf as frame_pointer_required may use it.  This function
      is called by sched_init before ira if scheduling is enabled.  */
@@ -2276,7 +2283,8 @@ ira_setup_eliminable_regset (void)
        frame pointer in LRA.  */

   if (frame_pointer_needed)
-    df_set_regs_ever_live (HARD_FRAME_POINTER_REGNUM, true);
+    for (i = 0; i < fp_reg_count; i++)
+      df_set_regs_ever_live (HARD_FRAME_POINTER_REGNUM + i, true);

   ira_no_alloc_regs = no_unit_alloc_regs;
   CLEAR_HARD_REG_SET (eliminable_regset);
@@ -2306,17 +2314,21 @@ ira_setup_eliminable_regset (void)
     }
   if (!HARD_FRAME_POINTER_IS_FRAME_POINTER)
     {
- if (!TEST_HARD_REG_BIT (crtl->asm_clobbers, HARD_FRAME_POINTER_REGNUM))
-	{
-	  SET_HARD_REG_BIT (eliminable_regset, HARD_FRAME_POINTER_REGNUM);
-	  if (frame_pointer_needed)
-	    SET_HARD_REG_BIT (ira_no_alloc_regs, HARD_FRAME_POINTER_REGNUM);
-	}
-      else if (frame_pointer_needed)
-	error ("%s cannot be used in %<asm%> here",
-	       reg_names[HARD_FRAME_POINTER_REGNUM]);
-      else
-	df_set_regs_ever_live (HARD_FRAME_POINTER_REGNUM, true);
+      for (i = 0; i < fp_reg_count; i++)
+	if (!TEST_HARD_REG_BIT (crtl->asm_clobbers,
+				HARD_FRAME_POINTER_REGNUM + i))
+	  {
+	    SET_HARD_REG_BIT (eliminable_regset,
+			      HARD_FRAME_POINTER_REGNUM + i);
+	    if (frame_pointer_needed)
+	      SET_HARD_REG_BIT (ira_no_alloc_regs,
+				HARD_FRAME_POINTER_REGNUM + i);
+	  }
+	else if (frame_pointer_needed)
+	  error ("%s cannot be used in %<asm%> here",
+		 reg_names[HARD_FRAME_POINTER_REGNUM + i]);
+	else
+	  df_set_regs_ever_live (HARD_FRAME_POINTER_REGNUM + i, true);
     }
 }


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