https://gcc.gnu.org/g:e84d5550a34fedc206bf1461071536e7450e746f

commit e84d5550a34fedc206bf1461071536e7450e746f
Author: Andrew Stubbs <[email protected]>
Date:   Tue Sep 15 15:05:04 2026 +0000

    amdgcn: Spill scalars to both SGPRs and AVGPRs
    
    The previous patch switched from spilling all VGPRs into AVGPRs to spilling
    VGPRs containing scalars into SGPRs.  That helps some cases, but had an
    unexpected impact on other benchmarks in which the SPGRs were under 
pressure.
    
    This patch allows scalars in VGPRs to spill into either register file, and
    fixes (and sometimes improves) the performance issues in all cases.
    
    Backport from mainline:
    
    gcc/ChangeLog:
    
            * config/gcn/gcn.cc (gcn_spill_class): Spill scalars in VGPRs to
            SCALAR_SPILL_REGS.
            (gcn_memory_move_cost): Handle SCALAR_SPILL_REGS.
            * config/gcn/gcn.h (enum reg_class): Add SCALAR_SPILL_REGS.
            (REG_CLASS_NAMES): Likewise.
            (REG_CLASS_CONTENTS): Likewise.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/gcn/avgpr-spill-int.c: Increase register pressure.
            * gcc.target/gcn/sgpr-spill-double.c: Allow some AVGPR spills.
            * gcc.target/gcn/sgpr-spill-int.c: Likewise.
            * gcc.target/gcn/sgpr-spill-long.c: Likewise.
            * gcc.target/gcn/sgpr-spill-short.c: Likewise.
    
    (cherry picked from commit d373724d1ddeef9b322b6b6078fc1de8dbe27791)

Diff:
---
 gcc/config/gcn/gcn.cc                            |   3 +-
 gcc/config/gcn/gcn.h                             |   8 ++
 gcc/testsuite/gcc.target/gcn/avgpr-spill-int.c   | 102 ++++++++++++++++++++++-
 gcc/testsuite/gcc.target/gcn/sgpr-spill-double.c |   6 +-
 gcc/testsuite/gcc.target/gcn/sgpr-spill-int.c    |   6 +-
 gcc/testsuite/gcc.target/gcn/sgpr-spill-long.c   |   6 +-
 gcc/testsuite/gcc.target/gcn/sgpr-spill-short.c  |   6 +-
 7 files changed, 131 insertions(+), 6 deletions(-)

diff --git a/gcc/config/gcn/gcn.cc b/gcc/config/gcn/gcn.cc
index 9c02d29c1850..0ed5ec6d81d0 100644
--- a/gcc/config/gcn/gcn.cc
+++ b/gcc/config/gcn/gcn.cc
@@ -860,7 +860,7 @@ gcn_spill_class (reg_class_t c, machine_mode mode)
       || c == VCC_CONDITIONAL_REG || c == EXEC_MASK_REG)
     return SGPR_REGS;
   else if (c == VGPR_REGS && !VECTOR_MODE_P (mode))
-    return SGPR_REGS;
+    return SCALAR_SPILL_REGS;
   else if (c == VGPR_REGS && TARGET_AVGPRS)
     return AVGPR_REGS;
   else
@@ -4075,6 +4075,7 @@ gcn_memory_move_cost (machine_mode mode, reg_class_t 
regclass, bool in)
       return (STORE_COST + (TARGET_CDNA2_MEM_COSTS ? 0 : 2)) * nregs;
     case ALL_REGS:
     case ALL_GPR_REGS:
+    case SCALAR_SPILL_REGS:
     case SRCDST_REGS:
       if (in)
        return (LOAD_COST + 2) * nregs;
diff --git a/gcc/config/gcn/gcn.h b/gcc/config/gcn/gcn.h
index c9e27193fb77..337d7d9811c1 100644
--- a/gcc/config/gcn/gcn.h
+++ b/gcc/config/gcn/gcn.h
@@ -412,6 +412,7 @@ enum reg_class
   AVGPR_REGS,
   ALL_VGPR_REGS,
   ALL_GPR_REGS,
+  SCALAR_SPILL_REGS,
   SRCDST_REGS,
   AFP_REGS,
   ALL_REGS,
@@ -440,6 +441,7 @@ enum reg_class
    "AVGPR_REGS",           \
    "ALL_VGPR_REGS",        \
    "ALL_GPR_REGS",         \
+   "SCALAR_SPILL_REGS",            \
    "SRCDST_REGS",          \
    "AFP_REGS",             \
    "ALL_REGS"              \
@@ -576,6 +578,12 @@ enum reg_class
      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,                      \
      0xffffffff, 0, 0, 0,                                                 \
      0, 0, 0, 0, 0, 0},                                                        
   \
+    /* SCALAR_SPILL_REGS.  */                                             \
+    {0xffffffff, 0xffffffff, 0xffffffff, 0xf1,                            \
+     0, 0, 0, 0,                                                          \
+     0, 0, 0, 0,                                                          \
+     0,                 0xffffffff, 0xffffffff, 0xffffffff,                    
   \
+     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0},      \
     /* SRCDST_REGS.  */                                                        
   \
     {0xffffffff, 0xffffffff, 0xffffffff,                                  \
      0xffffffff-NAMED_REG_MASK (VCCZ_REG),                                \
diff --git a/gcc/testsuite/gcc.target/gcn/avgpr-spill-int.c 
b/gcc/testsuite/gcc.target/gcn/avgpr-spill-int.c
index 462d67417c37..887ed4daf959 100644
--- a/gcc/testsuite/gcc.target/gcn/avgpr-spill-int.c
+++ b/gcc/testsuite/gcc.target/gcn/avgpr-spill-int.c
@@ -7,7 +7,7 @@ typedef int v32si __attribute__ ((__vector_size__ 
(sizeof(int)*32)));
 #define TYPE v32si
 #endif
 
-TYPE a[50];
+TYPE a[100];
 
 int f()
 {
@@ -61,6 +61,56 @@ int f()
   __asm__ volatile ("; fake <- %0" : "=v"(a[47]));
   __asm__ volatile ("; fake <- %0" : "=v"(a[48]));
   __asm__ volatile ("; fake <- %0" : "=v"(a[49]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[50]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[51]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[52]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[53]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[54]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[55]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[56]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[57]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[58]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[59]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[60]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[61]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[62]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[63]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[64]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[65]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[66]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[67]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[68]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[69]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[70]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[71]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[72]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[73]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[74]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[75]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[76]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[77]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[78]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[79]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[80]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[81]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[82]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[83]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[84]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[85]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[86]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[87]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[88]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[89]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[90]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[91]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[92]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[93]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[94]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[95]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[96]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[97]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[98]));
+  __asm__ volatile ("; fake <- %0" : "=v"(a[99]));
 
   __asm__ volatile ("; fake -> %0" :: "v"(a[0]));
   __asm__ volatile ("; fake -> %0" :: "v"(a[1]));
@@ -112,4 +162,54 @@ int f()
   __asm__ volatile ("; fake -> %0" :: "v"(a[47]));
   __asm__ volatile ("; fake -> %0" :: "v"(a[48]));
   __asm__ volatile ("; fake -> %0" :: "v"(a[49]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[50]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[51]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[52]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[53]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[54]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[55]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[56]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[57]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[58]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[59]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[60]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[61]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[62]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[63]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[64]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[65]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[66]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[67]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[68]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[69]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[70]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[71]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[72]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[73]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[74]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[75]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[76]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[77]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[78]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[79]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[80]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[81]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[82]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[83]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[84]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[85]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[86]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[87]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[88]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[89]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[90]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[91]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[92]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[93]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[94]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[95]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[96]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[97]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[98]));
+  __asm__ volatile ("; fake -> %0" :: "v"(a[99]));
 }
diff --git a/gcc/testsuite/gcc.target/gcn/sgpr-spill-double.c 
b/gcc/testsuite/gcc.target/gcn/sgpr-spill-double.c
index 6757a19d8c9c..910b4e650135 100644
--- a/gcc/testsuite/gcc.target/gcn/sgpr-spill-double.c
+++ b/gcc/testsuite/gcc.target/gcn/sgpr-spill-double.c
@@ -1,6 +1,10 @@
 /* { dg-do compile } */
 /* { dg-additional-options "-march=gfx908 -O1" } */
-/* { dg-final { scan-assembler-not "accvgpr" } } */
+
+/* Scalar values spilled out of VGPRs can be placed in either SGPRs or
+   AVGPRs, so both may appear here; the array is large enough that both
+   register files fill up and get used.  */
+/* { dg-final { scan-assembler "accvgpr" } } */
 
 /* Function epilogues use v6, but other registers may be a spill.  */
 /* { dg-final { scan-assembler "v_readlane.+, v\[12345789]" } } */
diff --git a/gcc/testsuite/gcc.target/gcn/sgpr-spill-int.c 
b/gcc/testsuite/gcc.target/gcn/sgpr-spill-int.c
index aed29442ce2c..536dba2544d5 100644
--- a/gcc/testsuite/gcc.target/gcn/sgpr-spill-int.c
+++ b/gcc/testsuite/gcc.target/gcn/sgpr-spill-int.c
@@ -1,6 +1,10 @@
 /* { dg-do compile } */
 /* { dg-additional-options "-march=gfx908 -O1" } */
-/* { dg-final { scan-assembler-not "accvgpr" } } */
+
+/* Scalar values spilled out of VGPRs can be placed in either SGPRs or
+   AVGPRs, so both may appear here; the array is large enough that both
+   register files fill up and get used.  */
+/* { dg-final { scan-assembler "accvgpr" } } */
 
 /* Function epilogues use v6, but other registers may be a spill.  */
 /* { dg-final { scan-assembler "v_readlane.+, v\[12345789]" } } */
diff --git a/gcc/testsuite/gcc.target/gcn/sgpr-spill-long.c 
b/gcc/testsuite/gcc.target/gcn/sgpr-spill-long.c
index 248624381b8d..57f6a7444ede 100644
--- a/gcc/testsuite/gcc.target/gcn/sgpr-spill-long.c
+++ b/gcc/testsuite/gcc.target/gcn/sgpr-spill-long.c
@@ -1,6 +1,10 @@
 /* { dg-do compile } */
 /* { dg-additional-options "-march=gfx908 -O1" } */
-/* { dg-final { scan-assembler-not "accvgpr" } } */
+
+/* Scalar values spilled out of VGPRs can be placed in either SGPRs or
+   AVGPRs, so both may appear here; the array is large enough that both
+   register files fill up and get used.  */
+/* { dg-final { scan-assembler "accvgpr" } } */
 
 /* Function epilogues use v6, but other registers may be a spill.  */
 /* { dg-final { scan-assembler "v_readlane.+, v\[12345789]" } } */
diff --git a/gcc/testsuite/gcc.target/gcn/sgpr-spill-short.c 
b/gcc/testsuite/gcc.target/gcn/sgpr-spill-short.c
index 35bd0d560895..f61a8eb58f98 100644
--- a/gcc/testsuite/gcc.target/gcn/sgpr-spill-short.c
+++ b/gcc/testsuite/gcc.target/gcn/sgpr-spill-short.c
@@ -1,6 +1,10 @@
 /* { dg-do compile } */
 /* { dg-additional-options "-march=gfx908 -O1" } */
-/* { dg-final { scan-assembler-not "accvgpr" } } */
+
+/* Scalar values spilled out of VGPRs can be placed in either SGPRs or
+   AVGPRs, so both may appear here; the array is large enough that both
+   register files fill up and get used.  */
+/* { dg-final { scan-assembler "accvgpr" } } */
 
 /* Function epilogues use v6, but other registers may be a spill.  */
 /* { dg-final { scan-assembler "v_readlane.+, v\[12345789]" } } */

Reply via email to