Check suitability of spill register for mode

Message ID 110adf99-5023-0f74-e090-a6ebe72498b2@codesourcery.com
State New
Headers show
Series
  • Check suitability of spill register for mode
Related show

Commit Message

Kwok Cheung Yeung Nov. 14, 2019, 12:34 p.m.
Hello

Currently, when choosing a spill register, GCC just picks the first 
available register in the register class returned by the 
TAQRGET_SPILL_CLASS hook that doesn't conflict.

On AMD GCN this can cause problems as DImode values stored in SGPRs must 
start on an even register number and TImode values on a multiple of 4. 
This is enforced by defining TARGET_HARD_REGNO_MODE_OK to be false when 
this condition is not satisfied. However, assign_spill_hard_regs does 
not check TARGET_HARD_REGNO_MODE_OK, so it can assign an unsuitable hard 
register for the mode. I have fixed this by rejecting spill registers 
that do not satisfy TARGET_HARD_REGNO_MODE_OK for the largest mode of 
the spilt register.

Built and tested for an AMD GCN target. This fixes failures in:

gcc.dg/vect/no-scevccp-outer-9.c
gcc.dg/vect/no-scevccp-outer-10.c

I have also ensured that the code bootstraps on x86_64, though it 
currently does not use spill registers.

Okay for trunk?

Kwok


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

	gcc/
	* lra-spills.c (assign_spill_hard_regs): Check that the spill
	register is suitable for the mode.
---
  gcc/lra-spills.c | 3 ++-
  1 file changed, 2 insertions(+), 1 deletion(-)

-- 
2.8.1

Comments

Vladimir Makarov Nov. 14, 2019, 9:17 p.m. | #1
On 11/14/19 7:34 AM, Kwok Cheung Yeung wrote:
> Hello

>

> Currently, when choosing a spill register, GCC just picks the first 

> available register in the register class returned by the 

> TAQRGET_SPILL_CLASS hook that doesn't conflict.

>

> On AMD GCN this can cause problems as DImode values stored in SGPRs 

> must start on an even register number and TImode values on a multiple 

> of 4. This is enforced by defining TARGET_HARD_REGNO_MODE_OK to be 

> false when this condition is not satisfied. However, 

> assign_spill_hard_regs does not check TARGET_HARD_REGNO_MODE_OK, so it 

> can assign an unsuitable hard register for the mode. I have fixed this 

> by rejecting spill registers that do not satisfy 

> TARGET_HARD_REGNO_MODE_OK for the largest mode of the spilt register.

>

> Built and tested for an AMD GCN target. This fixes failures in:

>

> gcc.dg/vect/no-scevccp-outer-9.c

> gcc.dg/vect/no-scevccp-outer-10.c

>

> I have also ensured that the code bootstraps on x86_64, though it 

> currently does not use spill registers.

>

> Okay for trunk?

>

Spilling into registers of another class was an experimental feature.  
On some x86-64 micro-architectures, it resulted in a worse performance 
code.  But I guess in your case, it is profitable.   I hope after your 
patches it can be switched on for some x86-64 micro-architectures.

As for the patch, it is OK to commit.  Thank you.

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

>

>     gcc/

>     * lra-spills.c (assign_spill_hard_regs): Check that the spill

>     register is suitable for the mode.

> ---

>  gcc/lra-spills.c | 3 ++-

>  1 file changed, 2 insertions(+), 1 deletion(-)

>

> diff --git a/gcc/lra-spills.c b/gcc/lra-spills.c

> index 54f76cc..8fbd3a8 100644

> --- a/gcc/lra-spills.c

> +++ b/gcc/lra-spills.c

> @@ -283,7 +283,8 @@ assign_spill_hard_regs (int *pseudo_regnos, int n)

>        for (k = 0; k < spill_class_size; k++)

>      {

>        hard_regno = ira_class_hard_regs[spill_class][k];

> -      if (TEST_HARD_REG_BIT (eliminable_regset, hard_regno))

> +      if (TEST_HARD_REG_BIT (eliminable_regset, hard_regno)

> +          || !targetm.hard_regno_mode_ok (hard_regno, mode))

>          continue;

>        if (! overlaps_hard_reg_set_p (conflict_hard_regs, mode, 

> hard_regno))

>          break;

Patch

diff --git a/gcc/lra-spills.c b/gcc/lra-spills.c
index 54f76cc..8fbd3a8 100644
--- a/gcc/lra-spills.c
+++ b/gcc/lra-spills.c
@@ -283,7 +283,8 @@  assign_spill_hard_regs (int *pseudo_regnos, int n)
        for (k = 0; k < spill_class_size; k++)
  	{
  	  hard_regno = ira_class_hard_regs[spill_class][k];
-	  if (TEST_HARD_REG_BIT (eliminable_regset, hard_regno))
+	  if (TEST_HARD_REG_BIT (eliminable_regset, hard_regno)
+	      || !targetm.hard_regno_mode_ok (hard_regno, mode))
  	    continue;
  	  if (! overlaps_hard_reg_set_p (conflict_hard_regs, mode, hard_regno))
  	    break;