aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJeevitha <jeevitha@linux.ibm.com>2023-12-25 04:06:54 -0600
committerJeevitha <jeevitha@linux.ibm.com>2023-12-25 04:06:54 -0600
commit1bbb169fe6f91451a2754f0b86301551db76ceba (patch)
tree194ecd7090fe39a0f3fe1844a4275795660ef3ff /gcc
parent0beeddd6b1b1cb41104c4df925323e8fc0437ba8 (diff)
downloadgcc-1bbb169fe6f91451a2754f0b86301551db76ceba.zip
gcc-1bbb169fe6f91451a2754f0b86301551db76ceba.tar.gz
gcc-1bbb169fe6f91451a2754f0b86301551db76ceba.tar.bz2
rs6000: Change GPR2 to volatile & non-fixed register for function that does not use TOC [PR110320]
Normally, GPR2 is the TOC pointer and is defined as a fixed and non-volatile register. However, it can be used as volatile for PCREL addressing. Therefore, modified r2 to be non-fixed in FIXED_REGISTERS and set it to fixed if it is not PCREL and also when the user explicitly requests TOC or fixed. If the register r2 is fixed, it is made as non-volatile. Changes in register preservation roles can be accomplished with the help of available target hooks (TARGET_CONDITIONAL_REGISTER_USAGE). 2023-12-24 Jeevitha Palanisamy <jeevitha@linux.ibm.com> gcc/ PR target/110320 * config/rs6000/rs6000.cc (rs6000_conditional_register_usage): Change GPR2 to volatile and non-fixed register for PCREL. * config/rs6000/rs6000.h (FIXED_REGISTERS): Modify GPR2 to not fixed. gcc/testsuite/ PR target/110320 * gcc.target/powerpc/pr110320-1.c: New testcase. * gcc.target/powerpc/pr110320-2.c: New testcase. * gcc.target/powerpc/pr110320-3.c: New testcase. Co-authored-by: Peter Bergner <bergner@linux.ibm.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/rs6000/rs6000.cc6
-rw-r--r--gcc/config/rs6000/rs6000.h2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr110320-1.c22
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr110320-2.c21
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr110320-3.c21
5 files changed, 70 insertions, 2 deletions
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index 09a5d29..6b9a40f 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -10199,9 +10199,13 @@ rs6000_conditional_register_usage (void)
for (i = 32; i < 64; i++)
fixed_regs[i] = call_used_regs[i] = 1;
+ /* For non PC-relative code, GPR2 is unavailable for register allocation. */
+ if (FIXED_R2 && !rs6000_pcrel_p ())
+ fixed_regs[2] = 1;
+
/* The TOC register is not killed across calls in a way that is
visible to the compiler. */
- if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+ if (fixed_regs[2] && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2))
call_used_regs[2] = 0;
if (DEFAULT_ABI == ABI_V4 && flag_pic == 2)
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index df44b86..98e046f 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -814,7 +814,7 @@ enum data_align { align_abi, align_opt, align_both };
#define FIXED_REGISTERS \
{/* GPRs */ \
- 0, 1, FIXED_R2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, FIXED_R13, 0, 0, \
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, FIXED_R13, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
/* FPRs */ \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
diff --git a/gcc/testsuite/gcc.target/powerpc/pr110320-1.c b/gcc/testsuite/gcc.target/powerpc/pr110320-1.c
new file mode 100644
index 0000000..9d49732
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr110320-1.c
@@ -0,0 +1,22 @@
+/* PR target/110320 */
+/* { dg-require-effective-target powerpc_elfv2 } */
+/* { dg-options "-O2 -mdejagnu-cpu=power10 -ffixed-r0 -ffixed-r11 -ffixed-r12" } */
+
+/* Ensure we use r2 as a normal volatile register for the code below.
+ The test case ensures all of the parameter registers r3 - r10 are used
+ and needed after we compute the expression "x + y" which requires a
+ temporary. The -ffixed-r* options disallow using the other volatile
+ registers r0, r11 and r12. That leaves RA to choose from r2 and the more
+ expensive non-volatile registers for the temporary to be assigned to, and
+ RA will always chooses the cheaper volatile r2 register. */
+
+extern long bar (long, long, long, long, long, long, long, long *);
+
+long
+foo (long r3, long r4, long r5, long r6, long r7, long r8, long r9, long *r10)
+{
+ *r10 = r3 + r4;
+ return bar (r3, r4, r5, r6, r7, r8, r9, r10);
+}
+
+/* { dg-final { scan-assembler {\madd 2,3,4\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr110320-2.c b/gcc/testsuite/gcc.target/powerpc/pr110320-2.c
new file mode 100644
index 0000000..9d6aefe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr110320-2.c
@@ -0,0 +1,21 @@
+/* PR target/110320 */
+/* { dg-require-effective-target powerpc_pcrel } */
+/* { dg-options "-O2 -mdejagnu-cpu=power10 -mno-pcrel -ffixed-r0 -ffixed-r11 -ffixed-r12" } */
+
+/* Ensure we don't use r2 as a normal volatile register for the code below.
+ The test case ensures all of the parameter registers r3 - r10 are used
+ and needed after we compute the expression "x + y" which requires a
+ temporary. The -ffixed-r* options disallow using the other volatile
+ registers r0, r11 and r12. That only leaves RA to choose from the more
+ expensive non-volatile registers for the temporary to be assigned to. */
+
+extern long bar (long, long, long, long, long, long, long, long *);
+
+long
+foo (long r3, long r4, long r5, long r6, long r7, long r8, long r9, long *r10)
+{
+ *r10 = r3 + r4;
+ return bar (r3, r4, r5, r6, r7, r8, r9, r10);
+}
+
+/* { dg-final { scan-assembler-not {\madd 2,3,4\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr110320-3.c b/gcc/testsuite/gcc.target/powerpc/pr110320-3.c
new file mode 100644
index 0000000..ffa8c63
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr110320-3.c
@@ -0,0 +1,21 @@
+/* PR target/110320 */
+/* { dg-require-effective-target powerpc_pcrel } */
+/* { dg-options "-O2 -mdejagnu-cpu=power10 -ffixed-r0 -ffixed-r2 -ffixed-r11 -ffixed-r12" } */
+
+/* Ensure we don't use r2 as a normal volatile register for the code below.
+ The test case ensures all of the parameter registers r3 - r10 are used
+ and needed after we compute the expression "x + y" which requires a
+ temporary. The -ffixed-r* options disallow using the other volatile
+ registers r0, r2, r11 and r12. That only leaves RA to choose from the more
+ expensive non-volatile registers for the temporary to be assigned to. */
+
+extern long bar (long, long, long, long, long, long, long, long *);
+
+long
+foo (long r3, long r4, long r5, long r6, long r7, long r8, long r9, long *r10)
+{
+ *r10 = r3 + r4;
+ return bar (r3, r4, r5, r6, r7, r8, r9, r10);
+}
+
+/* { dg-final { scan-assembler-not {\madd 2,3,4\M} } } */