Scalars located in VGPRs can be safely spilled to either AVGPRs or SGPRs,
but the AVGPRs are a much more limited resource, and are also much more
expensive to save around calls, so we should prefer to use SGPRs where we can.
SGPR spills will also work on devices that do not have AVGPRs.
The existing testcases for AVGPR spills were using scalars, and therefore
FAILed, so we change them to use vectors, and add new testcases for the scalar
case.
gcc/ChangeLog:
* config/gcn/gcn.cc (gcn_spill_class): Spill scalars to SGPRs.
gcc/testsuite/ChangeLog:
* gcc.target/gcn/avgpr-spill-double.c: Switch to vector type.
* gcc.target/gcn/avgpr-spill-int.c: Likewise.
* gcc.target/gcn/avgpr-spill-long.c: Likewise.
* gcc.target/gcn/avgpr-spill-short.c: Likewise.
* gcc.target/gcn/sgpr-spill-double.c: New test.
* gcc.target/gcn/sgpr-spill-int.c: New test.
* gcc.target/gcn/sgpr-spill-long.c: New test.
* gcc.target/gcn/sgpr-spill-short.c: New test.
---
gcc/config/gcn/gcn.cc | 8 ++++++--
gcc/testsuite/gcc.target/gcn/avgpr-spill-double.c | 3 ++-
gcc/testsuite/gcc.target/gcn/avgpr-spill-int.c | 3 ++-
gcc/testsuite/gcc.target/gcn/avgpr-spill-long.c | 3 ++-
gcc/testsuite/gcc.target/gcn/avgpr-spill-short.c | 3 ++-
gcc/testsuite/gcc.target/gcn/sgpr-spill-double.c | 10 ++++++++++
gcc/testsuite/gcc.target/gcn/sgpr-spill-int.c | 12 ++++++++++++
gcc/testsuite/gcc.target/gcn/sgpr-spill-long.c | 10 ++++++++++
gcc/testsuite/gcc.target/gcn/sgpr-spill-short.c | 10 ++++++++++
9 files changed, 56 insertions(+), 6 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/gcn/sgpr-spill-double.c
create mode 100644 gcc/testsuite/gcc.target/gcn/sgpr-spill-int.c
create mode 100644 gcc/testsuite/gcc.target/gcn/sgpr-spill-long.c
create mode 100644 gcc/testsuite/gcc.target/gcn/sgpr-spill-short.c
diff --git a/gcc/config/gcn/gcn.cc b/gcc/config/gcn/gcn.cc
index ed27acfb8a1..bbeaef3f927 100644
--- a/gcc/config/gcn/gcn.cc
+++ b/gcc/config/gcn/gcn.cc
@@ -854,13 +854,17 @@ gcn_can_split_p (machine_mode, rtx op)
if it is not possible or non-profitable. */
static reg_class_t
-gcn_spill_class (reg_class_t c, machine_mode /*mode */ )
+gcn_spill_class (reg_class_t c, machine_mode mode)
{
if (reg_classes_intersect_p (ALL_CONDITIONAL_REGS, c)
|| c == VCC_CONDITIONAL_REG || c == EXEC_MASK_REG)
return SGPR_REGS;
+ else if (c == VGPR_REGS && !VECTOR_MODE_P (mode))
+ return SGPR_REGS;
+ else if (c == VGPR_REGS && TARGET_AVGPRS)
+ return AVGPR_REGS;
else
- return c == VGPR_REGS && TARGET_AVGPRS ? AVGPR_REGS : NO_REGS;
+ return NO_REGS;
}
/* Implement TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS.
diff --git a/gcc/testsuite/gcc.target/gcn/avgpr-spill-double.c
b/gcc/testsuite/gcc.target/gcn/avgpr-spill-double.c
index 53853a4b075..3015f8ec6bb 100644
--- a/gcc/testsuite/gcc.target/gcn/avgpr-spill-double.c
+++ b/gcc/testsuite/gcc.target/gcn/avgpr-spill-double.c
@@ -2,6 +2,7 @@
/* { dg-additional-options "-march=gfx908 -O1" } */
/* { dg-final { scan-assembler "accvgpr" } } */
-#define TYPE double
+typedef double v32df __attribute__ ((__vector_size__ (sizeof(double)*32)));
+#define TYPE v32df
#include "avgpr-spill-int.c"
diff --git a/gcc/testsuite/gcc.target/gcn/avgpr-spill-int.c
b/gcc/testsuite/gcc.target/gcn/avgpr-spill-int.c
index 650f1587a1b..462d67417c3 100644
--- a/gcc/testsuite/gcc.target/gcn/avgpr-spill-int.c
+++ b/gcc/testsuite/gcc.target/gcn/avgpr-spill-int.c
@@ -2,8 +2,9 @@
/* { dg-additional-options "-march=gfx908 -O1" } */
/* { dg-final { scan-assembler "accvgpr" } } */
+typedef int v32si __attribute__ ((__vector_size__ (sizeof(int)*32)));
#ifndef TYPE
-#define TYPE int
+#define TYPE v32si
#endif
TYPE a[50];
diff --git a/gcc/testsuite/gcc.target/gcn/avgpr-spill-long.c
b/gcc/testsuite/gcc.target/gcn/avgpr-spill-long.c
index 51f887c4d59..1926fd9df0b 100644
--- a/gcc/testsuite/gcc.target/gcn/avgpr-spill-long.c
+++ b/gcc/testsuite/gcc.target/gcn/avgpr-spill-long.c
@@ -2,6 +2,7 @@
/* { dg-additional-options "-march=gfx908 -O1" } */
/* { dg-final { scan-assembler "accvgpr" } } */
-#define TYPE long
+typedef long v32di __attribute__ ((__vector_size__ (sizeof(long)*32)));
+#define TYPE v32di
#include "avgpr-spill-int.c"
diff --git a/gcc/testsuite/gcc.target/gcn/avgpr-spill-short.c
b/gcc/testsuite/gcc.target/gcn/avgpr-spill-short.c
index 983d2017ff5..71032e7674f 100644
--- a/gcc/testsuite/gcc.target/gcn/avgpr-spill-short.c
+++ b/gcc/testsuite/gcc.target/gcn/avgpr-spill-short.c
@@ -2,6 +2,7 @@
/* { dg-additional-options "-march=gfx908 -O1" } */
/* { dg-final { scan-assembler "accvgpr" } } */
-#define TYPE short
+typedef short v32hi __attribute__ ((__vector_size__ (sizeof(short)*32)));
+#define TYPE v32hi
#include "avgpr-spill-int.c"
diff --git a/gcc/testsuite/gcc.target/gcn/sgpr-spill-double.c
b/gcc/testsuite/gcc.target/gcn/sgpr-spill-double.c
new file mode 100644
index 00000000000..6757a19d8c9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/sgpr-spill-double.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=gfx908 -O1" } */
+/* { dg-final { scan-assembler-not "accvgpr" } } */
+
+/* Function epilogues use v6, but other registers may be a spill. */
+/* { dg-final { scan-assembler "v_readlane.+, v\[12345789]" } } */
+
+#define TYPE double
+
+#include "avgpr-spill-int.c"
diff --git a/gcc/testsuite/gcc.target/gcn/sgpr-spill-int.c
b/gcc/testsuite/gcc.target/gcn/sgpr-spill-int.c
new file mode 100644
index 00000000000..aed29442ce2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/sgpr-spill-int.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=gfx908 -O1" } */
+/* { dg-final { scan-assembler-not "accvgpr" } } */
+
+/* Function epilogues use v6, but other registers may be a spill. */
+/* { dg-final { scan-assembler "v_readlane.+, v\[12345789]" } } */
+
+#ifndef TYPE
+#define TYPE int
+#endif
+
+#include "avgpr-spill-int.c"
diff --git a/gcc/testsuite/gcc.target/gcn/sgpr-spill-long.c
b/gcc/testsuite/gcc.target/gcn/sgpr-spill-long.c
new file mode 100644
index 00000000000..248624381b8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/sgpr-spill-long.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=gfx908 -O1" } */
+/* { dg-final { scan-assembler-not "accvgpr" } } */
+
+/* Function epilogues use v6, but other registers may be a spill. */
+/* { dg-final { scan-assembler "v_readlane.+, v\[12345789]" } } */
+
+#define TYPE long
+
+#include "avgpr-spill-int.c"
diff --git a/gcc/testsuite/gcc.target/gcn/sgpr-spill-short.c
b/gcc/testsuite/gcc.target/gcn/sgpr-spill-short.c
new file mode 100644
index 00000000000..35bd0d56089
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/sgpr-spill-short.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=gfx908 -O1" } */
+/* { dg-final { scan-assembler-not "accvgpr" } } */
+
+/* Function epilogues use v6, but other registers may be a spill. */
+/* { dg-final { scan-assembler "v_readlane.+, v\[12345789]" } } */
+
+#define TYPE short
+
+#include "avgpr-spill-int.c"
--
2.54.0