$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