diff mbox

[AArch64] Implement HARD_REGNO_CALLER_SAVE_MODE

Message ID 000001cf6dff$8e4cf550$aae6dff0$@bolton@arm.com
State New
Headers show

Commit Message

Ian Bolton May 12, 2014, 4:30 p.m. UTC
Currently, on AArch64, when a caller-save register is saved/restored,
GCC is accessing the maximum size of the hard register.

So an SImode integer (4 bytes) value is being stored as DImode (8 bytes)
because the int registers are 8 bytes wide, and an SFmode float (4 bytes)
and DFmode double (8 bytes) are being stored as TImode (16 bytes) to
capture the full 128-bits of the vector register.

This patch corrects this, by implementing the HARD_REGNO_CALLER_SAVE_MODE
hook, which is called by LRA to determine the minimise size it might need
to save/restore.

Tested on GCC regression suite and verified impact on a number of examples.

OK for trunk?

Cheers,
Ian


2014-05-12  Ian Bolton  <ian.bolton@arm.com>

	* config/aarch64/aarch64-protos.h
(aarch64_hard_regno_caller_save_mode): New prototype.
	* config/aarch64/aarch64.c (aarch64_hard_regno_caller_save_mode):
New function.
	* config/aarch64/aarch64.h (HARD_REGNO_CALLER_SAVE_MODE): New macro.

Comments

Richard Earnshaw May 13, 2014, 8:42 a.m. UTC | #1
On 12/05/14 17:30, Ian Bolton wrote:
> Currently, on AArch64, when a caller-save register is saved/restored,
> GCC is accessing the maximum size of the hard register.
> 
> So an SImode integer (4 bytes) value is being stored as DImode (8 bytes)
> because the int registers are 8 bytes wide, and an SFmode float (4 bytes)
> and DFmode double (8 bytes) are being stored as TImode (16 bytes) to
> capture the full 128-bits of the vector register.
> 
> This patch corrects this, by implementing the HARD_REGNO_CALLER_SAVE_MODE
> hook, which is called by LRA to determine the minimise size it might need
> to save/restore.
> 
> Tested on GCC regression suite and verified impact on a number of examples.
> 
> OK for trunk?
> 
> Cheers,
> Ian
> 
> 
> 2014-05-12  Ian Bolton  <ian.bolton@arm.com>
> 
> 	* config/aarch64/aarch64-protos.h
> (aarch64_hard_regno_caller_save_mode): New prototype.
> 	* config/aarch64/aarch64.c (aarch64_hard_regno_caller_save_mode):
> New function.
> 	* config/aarch64/aarch64.h (HARD_REGNO_CALLER_SAVE_MODE): New macro.
> 

This is ok.

Watch your changelog entry though.  Lines should be wrapped before 80
columns (and continuations indented accordingly).

R.

> 
> aarch64-caller-save-fix-patch-v2.txt
> 
> 
> diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
> index 04cbc78..7cf7d9f 100644
> --- a/gcc/config/aarch64/aarch64-protos.h
> +++ b/gcc/config/aarch64/aarch64-protos.h
> @@ -202,6 +202,8 @@ enum aarch64_symbol_type aarch64_classify_symbol (rtx,
>  enum aarch64_symbol_type aarch64_classify_tls_symbol (rtx);
>  enum reg_class aarch64_regno_regclass (unsigned);
>  int aarch64_asm_preferred_eh_data_format (int, int);
> +enum machine_mode aarch64_hard_regno_caller_save_mode (unsigned, unsigned,
> +						       enum machine_mode);
>  int aarch64_hard_regno_mode_ok (unsigned, enum machine_mode);
>  int aarch64_hard_regno_nregs (unsigned, enum machine_mode);
>  int aarch64_simd_attr_length_move (rtx);
> diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
> index 8655f04..c2cc81b 100644
> --- a/gcc/config/aarch64/aarch64.c
> +++ b/gcc/config/aarch64/aarch64.c
> @@ -424,6 +424,24 @@ aarch64_hard_regno_mode_ok (unsigned regno, enum machine_mode mode)
>    return 0;
>  }
>  
> +/* Implement HARD_REGNO_CALLER_SAVE_MODE.  */
> +enum machine_mode
> +aarch64_hard_regno_caller_save_mode (unsigned regno, unsigned nregs,
> +				     enum machine_mode mode)
> +{
> +  /* Handle modes that fit within single registers.  */
> +  if (nregs == 1 && GET_MODE_SIZE (mode) <= 16)
> +    {
> +      if (GET_MODE_SIZE (mode) >= 4)
> +        return mode;
> +      else
> +        return SImode;
> +    }
> +  /* Fall back to generic for multi-reg and very large modes.  */
> +  else
> +    return choose_hard_reg_mode (regno, nregs, false);
> +}
> +
>  /* Return true if calls to DECL should be treated as
>     long-calls (ie called via a register).  */
>  static bool
> diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
> index c9b30d0..0574593 100644
> --- a/gcc/config/aarch64/aarch64.h
> +++ b/gcc/config/aarch64/aarch64.h
> @@ -824,6 +824,11 @@ do {									     \
>  
>  #define SHIFT_COUNT_TRUNCATED !TARGET_SIMD
>  
> +/* Choose appropriate mode for caller saves, so we do the minimum
> +   required size of load/store.  */
> +#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \
> +  aarch64_hard_regno_caller_save_mode ((REGNO), (NREGS), (MODE))
> +
>  /* Callee only saves lower 64-bits of a 128-bit register.  Tell the
>     compiler the callee clobbers the top 64-bits when restoring the
>     bottom 64-bits.  */
>
diff mbox

Patch

diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 04cbc78..7cf7d9f 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -202,6 +202,8 @@  enum aarch64_symbol_type aarch64_classify_symbol (rtx,
 enum aarch64_symbol_type aarch64_classify_tls_symbol (rtx);
 enum reg_class aarch64_regno_regclass (unsigned);
 int aarch64_asm_preferred_eh_data_format (int, int);
+enum machine_mode aarch64_hard_regno_caller_save_mode (unsigned, unsigned,
+						       enum machine_mode);
 int aarch64_hard_regno_mode_ok (unsigned, enum machine_mode);
 int aarch64_hard_regno_nregs (unsigned, enum machine_mode);
 int aarch64_simd_attr_length_move (rtx);
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 8655f04..c2cc81b 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -424,6 +424,24 @@  aarch64_hard_regno_mode_ok (unsigned regno, enum machine_mode mode)
   return 0;
 }
 
+/* Implement HARD_REGNO_CALLER_SAVE_MODE.  */
+enum machine_mode
+aarch64_hard_regno_caller_save_mode (unsigned regno, unsigned nregs,
+				     enum machine_mode mode)
+{
+  /* Handle modes that fit within single registers.  */
+  if (nregs == 1 && GET_MODE_SIZE (mode) <= 16)
+    {
+      if (GET_MODE_SIZE (mode) >= 4)
+        return mode;
+      else
+        return SImode;
+    }
+  /* Fall back to generic for multi-reg and very large modes.  */
+  else
+    return choose_hard_reg_mode (regno, nregs, false);
+}
+
 /* Return true if calls to DECL should be treated as
    long-calls (ie called via a register).  */
 static bool
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index c9b30d0..0574593 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -824,6 +824,11 @@  do {									     \
 
 #define SHIFT_COUNT_TRUNCATED !TARGET_SIMD
 
+/* Choose appropriate mode for caller saves, so we do the minimum
+   required size of load/store.  */
+#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \
+  aarch64_hard_regno_caller_save_mode ((REGNO), (NREGS), (MODE))
+
 /* Callee only saves lower 64-bits of a 128-bit register.  Tell the
    compiler the callee clobbers the top 64-bits when restoring the
    bottom 64-bits.  */