$GP is used for expanding GOT load, and in the afterward passes,
we will try to use a temporary register instead.

If sucess, we have no need to store and reload $gp. The example
of failure is that the function calls a preemtive function.

We shouldn't use $GP for any other purpose in the code we generate.
If a user's inline asm code clobbers $GP, it's their duty to save
and restore $GP.

gcc
        * config/mips/mips.cc (mips_compute_frame_info): If another
        register is used as global_pointer, mark $GP live false.

gcc/testsuite
        * gcc.target/mips/mips.exp (mips_option_groups):
        Add -mxgot/-mno-xgot options.
        * gcc.target/mips/xgot-n32-avoid-gp.c: New test.
        * gcc.target/mips/xgot-n32-need-gp.c: New test.
---
 gcc/config/mips/mips.cc                           |  2 ++
 gcc/testsuite/gcc.target/mips/mips.exp            |  1 +
 gcc/testsuite/gcc.target/mips/xgot-n32-avoid-gp.c | 11 +++++++++++
 gcc/testsuite/gcc.target/mips/xgot-n32-need-gp.c  | 11 +++++++++++
 4 files changed, 25 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/mips/xgot-n32-avoid-gp.c
 create mode 100644 gcc/testsuite/gcc.target/mips/xgot-n32-need-gp.c

diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc
index e752019b5e2..30e99811ff6 100644
--- a/gcc/config/mips/mips.cc
+++ b/gcc/config/mips/mips.cc
@@ -11353,6 +11353,8 @@ mips_compute_frame_info (void)
      in, which is why the global_pointer field is initialised here and not
      earlier.  */
   cfun->machine->global_pointer = mips_global_pointer ();
+  if (cfun->machine->global_pointer != GLOBAL_POINTER_REGNUM)
+    df_set_regs_ever_live (GLOBAL_POINTER_REGNUM, false);
 
   offset = frame->args_size + frame->cprestore_size;
 
diff --git a/gcc/testsuite/gcc.target/mips/mips.exp 
b/gcc/testsuite/gcc.target/mips/mips.exp
index 9f8d533cfa5..e028bc93b40 100644
--- a/gcc/testsuite/gcc.target/mips/mips.exp
+++ b/gcc/testsuite/gcc.target/mips/mips.exp
@@ -266,6 +266,7 @@ set mips_option_groups {
     stack-protector "-fstack-protector"
     stdlib "REQUIRES_STDLIB"
     unaligned-access "-m(no-|)unaligned-access"
+    xgot "-m(no-|)xgot"
 }
 
 for { set option 0 } { $option < 32 } { incr option } {
diff --git a/gcc/testsuite/gcc.target/mips/xgot-n32-avoid-gp.c 
b/gcc/testsuite/gcc.target/mips/xgot-n32-avoid-gp.c
new file mode 100644
index 00000000000..3f52fc5a765
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/xgot-n32-avoid-gp.c
@@ -0,0 +1,11 @@
+/* Check if we skip store and load gp if there is no stub function call.  */
+/* { dg-options "-mips64r2 -mxgot -mabi=n32 -fPIC" } */
+
+extern int a;
+int
+foo ()
+{
+  return a;
+}
+/* { dg-final { scan-assembler-not "\tsd\t\\\$28," } } */
+/* { dg-final { scan-assembler-not "\tld\t\\\$28," } } */
diff --git a/gcc/testsuite/gcc.target/mips/xgot-n32-need-gp.c 
b/gcc/testsuite/gcc.target/mips/xgot-n32-need-gp.c
new file mode 100644
index 00000000000..631409cb7fe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/xgot-n32-need-gp.c
@@ -0,0 +1,11 @@
+/* We cannot skip store and load gp if there is stub function call.  */
+/* { dg-options "-mips64r2 -mxgot -mabi=n32 -fPIC" } */
+
+extern int f();
+int
+foo ()
+{
+  return f();
+}
+/* { dg-final { scan-assembler "\tsd\t\\\$28," } } */
+/* { dg-final { scan-assembler "\tld\t\\\$28," } } */
-- 
2.39.2

Reply via email to