microMIPS/GCC: Fix PIC call relaxation
diff mbox

Message ID alpine.DEB.2.20.17.1611121200040.10580@tp.orcam.me.uk
State Accepted
Headers show

Commit Message

Maciej W. Rozycki Nov. 12, 2016, 1:44 p.m. UTC
Fix `-mrelax-pic-calls' support for microMIPS code where the relocation 
produced is supposed to be R_MICROMIPS_JALR rather than R_MIPS_JALR.  
The lack of short delay support comes from a missed update to this code 
for microMIPS support and can be relieved as JALRS and JRS instructions 
can be relaxed to BALS and B instructions respectively, so do that as 
well.

By doing so complement commit r196828 ("microMIPS gcc support"), 
<https://gcc.gnu.org/ml/gcc-patches/2013-02/msg01103.html>, which is the 
original change that introduced microMIPS support, in particular to 
MIPS_CALL, which is where this code previously resided.

Adjust the test suite accordingly, limiting R_MICROMIPS_JALR cases to 
regular MIPS code only, and adding corresponding R_MICROMIPS_JALR cases 
for microMIPS code.

	gcc/
	* config/mips/mips.c (mips_output_jump): Output R_MICROMIPS_JALR
	rather than R_MIPS_JALR relocation in microMIPS code.  Do not
	cancel short delay slots in PIC call relaxation.

	gcc/testsuite/
	* gcc.target/mips/call-1.c (dg-options): Add `-mno-micromips'.
	(dg-final): Remove microMIPS JALRS mnemonic matching.
	* gcc.target/mips/call-2.c (dg-options): Add `-mno-micromips'.
	(dg-final): Remove microMIPS JALRS mnemonic matching.
	* gcc.target/mips/call-3.c (dg-options): Add `-mno-micromips'.
	(dg-final): Remove microMIPS JALRS mnemonic matching.
	* gcc.target/mips/call-4.c (dg-options): Add `-mno-micromips'.
	* gcc.target/mips/call-5.c (dg-options): Add `-mno-micromips'.
	* gcc.target/mips/call-6.c (dg-options): Add `-mno-micromips'.
	* gcc.target/mips/call-1u.c: New test case.
	* gcc.target/mips/call-2u.c: New test case.
	* gcc.target/mips/call-3u.c: New test case.
	* gcc.target/mips/call-4u.c: New test case.
	* gcc.target/mips/call-5u.c: New test case.
	* gcc.target/mips/call-6u.c: New test case.
---
 NB the use of this feature for microMIPS is limited because short 
encodings of register jump instructions usually do not have their branch 
counterparts and long encodings typically are not used.  However at least 
tail calls can be converted if the jump target is in range, as can calls 
in `-minsn32' code.  Perhaps we could switch to producing `j[al]r[s].32' 
in the `-mrelax-pic-calls' mode like GAS does with the `jal' and `j' 
microMIPS macros in PIC code.

 This change, with commit r235825 reverted (see PR rtl-optimization/78325, 
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78325>), has passed 
regression testing with the `mips-mti-linux-gnu' target, using the 
big-endian regular MIPS o32 multilib.

 I think verifying with a microMIPS multilib would be worth doing too, 
however it would take a long time, owing to readily available microMIPS 
hardware being limited in terms of performance; and I am not currently set 
up for simulator testing.  It is a fix for an evident code generation bug 
though and by the nature of the change switching the relocation type only 
and permitting short delay slots with PIC call relaxation any reasonably 
possible fallout would only happen with the assembler and/or linker.  So 
while I do intend to push this through microMIPS testing eventually, it 
will likely take a bit yet (with the bit being weeks to months).

 Let me know if the lack of microMIPS results would be a problem for this 
patch's acceptance.  Otherwise, OK to apply?

  Maciej

gcc-umips-jalr.diff

Comments

Matthew Fortune Nov. 16, 2016, 10:32 a.m. UTC | #1
Maciej Rozycki <Maciej.Rozycki@imgtec.com> writes:
> Fix `-mrelax-pic-calls' support for microMIPS code where the relocation
> produced is supposed to be R_MICROMIPS_JALR rather than R_MIPS_JALR.
> The lack of short delay support comes from a missed update to this code
> for microMIPS support and can be relieved as JALRS and JRS instructions
> can be relaxed to BALS and B instructions respectively, so do that as
> well.

Thanks. I didn't follow the background to this optimisation when I added
the compact branch support so opted to retain the pre-existing behaviour.

> By doing so complement commit r196828 ("microMIPS gcc support"),
> <https://gcc.gnu.org/ml/gcc-patches/2013-02/msg01103.html>, which is the
> original change that introduced microMIPS support, in particular to
> MIPS_CALL, which is where this code previously resided.
> 
> Adjust the test suite accordingly, limiting R_MICROMIPS_JALR cases to

Typo fwiw: Should say R_MIPS_JALR for MIPS code.

> regular MIPS code only, and adding corresponding R_MICROMIPS_JALR cases
> for microMIPS code.
> 
> 	gcc/
> 	* config/mips/mips.c (mips_output_jump): Output R_MICROMIPS_JALR
> 	rather than R_MIPS_JALR relocation in microMIPS code.  Do not
> 	cancel short delay slots in PIC call relaxation.
> 
> 	gcc/testsuite/
> 	* gcc.target/mips/call-1.c (dg-options): Add `-mno-micromips'.
> 	(dg-final): Remove microMIPS JALRS mnemonic matching.
> 	* gcc.target/mips/call-2.c (dg-options): Add `-mno-micromips'.
> 	(dg-final): Remove microMIPS JALRS mnemonic matching.
> 	* gcc.target/mips/call-3.c (dg-options): Add `-mno-micromips'.
> 	(dg-final): Remove microMIPS JALRS mnemonic matching.
> 	* gcc.target/mips/call-4.c (dg-options): Add `-mno-micromips'.
> 	* gcc.target/mips/call-5.c (dg-options): Add `-mno-micromips'.
> 	* gcc.target/mips/call-6.c (dg-options): Add `-mno-micromips'.
> 	* gcc.target/mips/call-1u.c: New test case.
> 	* gcc.target/mips/call-2u.c: New test case.
> 	* gcc.target/mips/call-3u.c: New test case.
> 	* gcc.target/mips/call-4u.c: New test case.
> 	* gcc.target/mips/call-5u.c: New test case.
> 	* gcc.target/mips/call-6u.c: New test case.
> ---
>  NB the use of this feature for microMIPS is limited because short
> encodings of register jump instructions usually do not have their branch
> counterparts and long encodings typically are not used.  However at
> least
> tail calls can be converted if the jump target is in range, as can calls
> in `-minsn32' code.  Perhaps we could switch to producing `j[al]r[s].32'
> in the `-mrelax-pic-calls' mode like GAS does with the `jal' and `j'
> microMIPS macros in PIC code.

Does the linker do anything for R_MICROMIPS_JALR currently? From memory
I seem to think it was mostly ignored. Is there any risk with older linkers
by introducing R_MICROMIPS_JALR in GCC generated code?

>  Let me know if the lack of microMIPS results would be a problem for
> this
> patch's acceptance.

Not a problem. We will pick this up as part of testing for the release.

There is a bit of coding style fuzz in the testcases but it is
pre-existing from the code you duplicated so I don't think it needs
fixing.

>  Otherwise, OK to apply?

OK, as long as you can say there is no risk with the new reloc and older
linkers.

Thanks,
Matthew
Maciej W. Rozycki Nov. 16, 2016, 9:07 p.m. UTC | #2
On Wed, 16 Nov 2016, Matthew Fortune wrote:

> > Fix `-mrelax-pic-calls' support for microMIPS code where the relocation
> > produced is supposed to be R_MICROMIPS_JALR rather than R_MIPS_JALR.
> > The lack of short delay support comes from a missed update to this code
> > for microMIPS support and can be relieved as JALRS and JRS instructions
> > can be relaxed to BALS and B instructions respectively, so do that as
> > well.
> 
> Thanks. I didn't follow the background to this optimisation when I added
> the compact branch support so opted to retain the pre-existing behaviour.

 In any case there was no deliberate choice made here, but just a missed 
update along the original microMIPS change.

> > By doing so complement commit r196828 ("microMIPS gcc support"),
> > <https://gcc.gnu.org/ml/gcc-patches/2013-02/msg01103.html>, which is the
> > original change that introduced microMIPS support, in particular to
> > MIPS_CALL, which is where this code previously resided.
> > 
> > Adjust the test suite accordingly, limiting R_MICROMIPS_JALR cases to
> 
> Typo fwiw: Should say R_MIPS_JALR for MIPS code.

 Indeed.  We don't use GIT style commit logs though so I can't correct it 
and your spotting will just stay here for posterity.

> >  NB the use of this feature for microMIPS is limited because short
> > encodings of register jump instructions usually do not have their branch
> > counterparts and long encodings typically are not used.  However at
> > least
> > tail calls can be converted if the jump target is in range, as can calls
> > in `-minsn32' code.  Perhaps we could switch to producing `j[al]r[s].32'
> > in the `-mrelax-pic-calls' mode like GAS does with the `jal' and `j'
> > microMIPS macros in PIC code.
> 
> Does the linker do anything for R_MICROMIPS_JALR currently? From memory
> I seem to think it was mostly ignored. Is there any risk with older linkers
> by introducing R_MICROMIPS_JALR in GCC generated code?

 For the o32 ABI the R_MICROMIPS_JALR reloc is currently effectively 
ignored by the BFD linker, although some preparations for handling have 
been made and therefore there are two switch cases where it appears.

 Actual handling for PIC call relaxation is only included for R_MIPS_JALR 
in `mips_elf_perform_relocation' though, where the actual JALR and JR 
instruction encoding is checked, which is different between the regular 
MIPS and the microMIPS ISAs.

 The presence of R_MIPS_JALR in microMIPS code will lead to an incorrect 
internal `cross_mode_jump_p' setting in `mips_elf_calculate_relocation', 
however this does not cause harm because `mips_elf_perform_relocation' 
code will check instruction encoding.

 For n32 and n64 ABIs the BFD linker handling of R_MIPS_JALR is done in 
`_bfd_mips_relax_section' instead and does not take `cross_mode_jump_p' 
into account, however the instruction encoding is likewise checked, so no 
harm there either.  I plan to remove this function, perhaps before 2.28 
even, as it is duplicated by the corresponding o32 handler now, but 
suffers from considerable bitrot.

 I plan to implement the missing R_MICROMIPS_JALR handling in the BFD 
linker sometime as well, although it may take a little bit yet.  As I 
noted in the original change description, the usable cases are limited, so 
there isn't as much incentive to have this implemented as there was with 
the regular MIPS ISA, which is also probably the reason why this was 
missed from the original microMIPS support patches.

> >  Let me know if the lack of microMIPS results would be a problem for
> > this
> > patch's acceptance.
> 
> Not a problem. We will pick this up as part of testing for the release.
> 
> There is a bit of coding style fuzz in the testcases but it is
> pre-existing from the code you duplicated so I don't think it needs
> fixing.

 I missed that indeed, having copied the test cases verbatim.  I wonder if 
we shouldn't actually factor out these test case bodies to shared .h files 
included from corresponding regular MIPS and microMIPS test cases, and 
then have the formatting fixes applied there instead.

> >  Otherwise, OK to apply?
> 
> OK, as long as you can say there is no risk with the new reloc and older
> linkers.

 As double-checked and documented above I can say there is no risk, so I 
have committed this change now.  Thanks for your review.

  Maciej

Patch
diff mbox

Index: gcc/gcc/config/mips/mips.c
===================================================================
--- gcc.orig/gcc/config/mips/mips.c	2016-11-11 19:55:39.727013997 +0000
+++ gcc/gcc/config/mips/mips.c	2016-11-11 21:02:20.655335552 +0000
@@ -13611,12 +13611,9 @@  mips_output_jump (rtx *operands, int tar
 	s += sprintf (s, ".option\tpic0\n\t");
 
       if (reg_p && mips_get_pic_call_symbol (operands, size_opno))
-	{
-	  s += sprintf (s, "%%*.reloc\t1f,R_MIPS_JALR,%%%d\n1:\t", size_opno);
-	  /* Not sure why this shouldn't permit a short delay but it did not
-	     allow it before so we still don't allow it.  */
-	  short_delay = "";
-	}
+	s += sprintf (s, "%%*.reloc\t1f,%s,%%%d\n1:\t",
+		      TARGET_MICROMIPS ? "R_MICROMIPS_JALR" : "R_MIPS_JALR",
+		      size_opno);
       else
 	s += sprintf (s, "%%*");
 
Index: gcc/gcc/testsuite/gcc.target/mips/call-1.c
===================================================================
--- gcc.orig/gcc/testsuite/gcc.target/mips/call-1.c	2016-11-12 10:09:33.548220788 +0000
+++ gcc/gcc/testsuite/gcc.target/mips/call-1.c	2016-11-12 10:09:55.004824221 +0000
@@ -1,8 +1,8 @@ 
-/* { dg-options "-mrelax-pic-calls -mshared -foptimize-sibling-calls -mabi=32" } */
+/* { dg-options "-mno-micromips -mrelax-pic-calls -mshared -foptimize-sibling-calls -mabi=32" } */
 /* { dg-skip-if "requires -foptimize-sibling-calls" { *-*-* } { "-O0" } { "" } } */
-/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal\n1:\tjalrc?s?\t" } } */
-/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal2\n1:\tjalrc?s?\t" } } */
-/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,staticfunc\n1:\tjalrc?s?\t" } } */
+/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal\n1:\tjalrc?\t" } } */
+/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal2\n1:\tjalrc?\t" } } */
+/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,staticfunc\n1:\tjalrc?\t" } } */
 /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail\n1:\tjrc?\t" } } */
 /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail2\n1:\tjrc?\t" } } */
 /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail3\n1:\tjrc?\t" } } */
Index: gcc/gcc/testsuite/gcc.target/mips/call-1u.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/gcc/testsuite/gcc.target/mips/call-1u.c	2016-11-12 10:09:55.019918358 +0000
@@ -0,0 +1,51 @@ 
+/* { dg-options "-mmicromips -mrelax-pic-calls -mshared -foptimize-sibling-calls -mabi=32" } */
+/* { dg-skip-if "requires -foptimize-sibling-calls" { *-*-* } { "-O0" } { "" } } */
+/* { dg-final { scan-assembler "\\.reloc\t1f,R_MICROMIPS_JALR,normal\n1:\tjalrs?\t" } } */
+/* { dg-final { scan-assembler "\\.reloc\t1f,R_MICROMIPS_JALR,normal2\n1:\tjalrs?\t" } } */
+/* { dg-final { scan-assembler "\\.reloc\t1f,R_MICROMIPS_JALR,staticfunc\n1:\tjalrs?\t" } } */
+/* { dg-final { scan-assembler "\\.reloc\t1f,R_MICROMIPS_JALR,tail\n1:\tjrc?\t" } } */
+/* { dg-final { scan-assembler "\\.reloc\t1f,R_MICROMIPS_JALR,tail2\n1:\tjrc?\t" } } */
+/* { dg-final { scan-assembler "\\.reloc\t1f,R_MICROMIPS_JALR,tail3\n1:\tjrc?\t" } } */
+/* { dg-final { scan-assembler "\\.reloc\t1f,R_MICROMIPS_JALR,tail4\n1:\tjrc?\t" } } */
+
+__attribute__ ((noinline)) static void staticfunc () { asm (""); }
+int normal ();
+void normal2 ();
+
+int
+NOMIPS16 f (int *p)
+{
+  *p = normal ();
+  normal2 ();
+  staticfunc ();
+  return 1;
+}
+
+int tail ();
+
+int
+NOMIPS16 h ()
+{
+  return tail ();
+}
+
+void tail2 ();
+
+NOMIPS16 void g ()
+{
+  tail2 ();
+}
+
+__attribute__ ((visibility ("hidden"))) void tail3 ();
+
+NOMIPS16 void j ()
+{
+  tail3 ();
+}
+
+__attribute__ ((noinline)) static void tail4 () { asm (""); }
+
+NOMIPS16 void k ()
+{
+  tail4 ();
+}
Index: gcc/gcc/testsuite/gcc.target/mips/call-2.c
===================================================================
--- gcc.orig/gcc/testsuite/gcc.target/mips/call-2.c	2016-11-12 10:09:33.570398493 +0000
+++ gcc/gcc/testsuite/gcc.target/mips/call-2.c	2016-11-12 10:09:55.031182509 +0000
@@ -1,6 +1,6 @@ 
 /* See through some simple data-flow.  */
-/* { dg-options "-mrelax-pic-calls" } */
-/* { dg-final { scan-assembler-times "\\.reloc\t1f,R_MIPS_JALR,g\n1:\tjalrc?s?\t" 2 } } */
+/* { dg-options "-mno-micromips -mrelax-pic-calls" } */
+/* { dg-final { scan-assembler-times "\\.reloc\t1f,R_MIPS_JALR,g\n1:\tjalrc?\t" 2 } } */
 
 extern void g (void);
 
Index: gcc/gcc/testsuite/gcc.target/mips/call-2u.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/gcc/testsuite/gcc.target/mips/call-2u.c	2016-11-12 10:09:55.053655589 +0000
@@ -0,0 +1,13 @@ 
+/* See through some simple data-flow.  */
+/* { dg-options "-mmicromips -mrelax-pic-calls" } */
+/* { dg-final { scan-assembler-times "\\.reloc\t1f,R_MICROMIPS_JALR,g\n1:\tjalrs?\t" 2 } } */
+
+extern void g (void);
+
+int
+NOMIPS16 f ()
+{
+  g ();
+  g ();
+  return 1;
+}
Index: gcc/gcc/testsuite/gcc.target/mips/call-3.c
===================================================================
--- gcc.orig/gcc/testsuite/gcc.target/mips/call-3.c	2016-11-12 10:09:33.586675251 +0000
+++ gcc/gcc/testsuite/gcc.target/mips/call-3.c	2016-11-12 10:09:55.065818862 +0000
@@ -1,5 +1,5 @@ 
-/* { dg-options "-mrelax-pic-calls -mno-shared" } */
-/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,g\n1:\tjalrc?s?\t" } } */
+/* { dg-options "-mno-micromips -mrelax-pic-calls -mno-shared" } */
+/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,g\n1:\tjalrc?\t" } } */
 /* { dg-require-visibility "" } */
 
 __attribute__ ((visibility ("hidden"))) void g ();
Index: gcc/gcc/testsuite/gcc.target/mips/call-3u.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/gcc/testsuite/gcc.target/mips/call-3u.c	2016-11-12 10:09:55.086985454 +0000
@@ -0,0 +1,12 @@ 
+/* { dg-options "-mmicromips -mrelax-pic-calls -mno-shared" } */
+/* { dg-final { scan-assembler "\\.reloc\t1f,R_MICROMIPS_JALR,g\n1:\tjalrs?\t" } } */
+/* { dg-require-visibility "" } */
+
+__attribute__ ((visibility ("hidden"))) void g ();
+
+int
+NOMIPS16 f ()
+{
+  g ();
+  return 1;
+}
Index: gcc/gcc/testsuite/gcc.target/mips/call-4.c
===================================================================
--- gcc.orig/gcc/testsuite/gcc.target/mips/call-4.c	2016-11-12 10:09:33.609850707 +0000
+++ gcc/gcc/testsuite/gcc.target/mips/call-4.c	2016-11-12 10:09:55.095097004 +0000
@@ -1,5 +1,5 @@ 
 /* See through some simple data-flow.  */
-/* { dg-options "-mrelax-pic-calls" } */
+/* { dg-options "-mno-micromips -mrelax-pic-calls" } */
 /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,g\n1:\tjalrc?\t" } } */
 
 extern void g (void);
Index: gcc/gcc/testsuite/gcc.target/mips/call-4u.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/gcc/testsuite/gcc.target/mips/call-4u.c	2016-11-12 10:09:55.112294350 +0000
@@ -0,0 +1,12 @@ 
+/* See through some simple data-flow.  */
+/* { dg-options "-mmicromips -mrelax-pic-calls" } */
+/* { dg-final { scan-assembler "\\.reloc\t1f,R_MICROMIPS_JALR,g\n1:\tjalrs?\t" } } */
+
+extern void g (void);
+
+int
+NOMIPS16 f (int i)
+{
+  while (i--)
+    g ();
+}
Index: gcc/gcc/testsuite/gcc.target/mips/call-5.c
===================================================================
--- gcc.orig/gcc/testsuite/gcc.target/mips/call-5.c	2016-11-12 10:09:33.627014656 +0000
+++ gcc/gcc/testsuite/gcc.target/mips/call-5.c	2016-11-12 10:09:55.122364192 +0000
@@ -1,6 +1,6 @@ 
 /* Like call-1.c, but for n32.  We cannot use sibling calls for tail and tail2
    in this case (PR target/57260).  */
-/* { dg-options "-mrelax-pic-calls -mshared -foptimize-sibling-calls -mabi=n32" } */
+/* { dg-options "-mno-micromips -mrelax-pic-calls -mshared -foptimize-sibling-calls -mabi=n32" } */
 /* { dg-skip-if "requires -foptimize-sibling-calls" { *-*-* } { "-O0" } { "" } } */
 /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal\n1:\tjalrc?\t" } } */
 /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal2\n1:\tjalrc?\t" } } */
Index: gcc/gcc/testsuite/gcc.target/mips/call-5u.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/gcc/testsuite/gcc.target/mips/call-5u.c	2016-11-12 10:09:55.145543603 +0000
@@ -0,0 +1,53 @@ 
+/* Like call-1.c, but for n32.  We cannot use sibling calls for tail and tail2
+   in this case (PR target/57260).  */
+/* { dg-options "-mmicromips -mrelax-pic-calls -mshared -foptimize-sibling-calls -mabi=n32" } */
+/* { dg-skip-if "requires -foptimize-sibling-calls" { *-*-* } { "-O0" } { "" } } */
+/* { dg-final { scan-assembler "\\.reloc\t1f,R_MICROMIPS_JALR,normal\n1:\tjalrs?\t" } } */
+/* { dg-final { scan-assembler "\\.reloc\t1f,R_MICROMIPS_JALR,normal2\n1:\tjalrs?\t" } } */
+/* { dg-final { scan-assembler "\\.reloc\t1f,R_MICROMIPS_JALR,staticfunc\n1:\tjalrs?\t" } } */
+/* { dg-final { scan-assembler "\\.reloc\t1f,R_MICROMIPS_JALR,tail\n1:\tjalrs?\t" } } */
+/* { dg-final { scan-assembler "\\.reloc\t1f,R_MICROMIPS_JALR,tail2\n1:\tjalrs?\t" } } */
+/* { dg-final { scan-assembler "\\.reloc\t1f,R_MICROMIPS_JALR,tail3\n1:\tjrc?\t" } } */
+/* { dg-final { scan-assembler "\\.reloc\t1f,R_MICROMIPS_JALR,tail4\n1:\tjrc?\t" } } */
+
+__attribute__ ((noinline)) static void staticfunc () { asm (""); }
+int normal ();
+void normal2 ();
+
+int
+NOMIPS16 f (int *p)
+{
+  *p = normal ();
+  normal2 ();
+  staticfunc ();
+  return 1;
+}
+
+int tail ();
+
+int
+NOMIPS16 h ()
+{
+  return tail ();
+}
+
+void tail2 ();
+
+NOMIPS16 void g ()
+{
+  tail2 ();
+}
+
+__attribute__ ((visibility ("hidden"))) void tail3 ();
+
+NOMIPS16 void j ()
+{
+  tail3 ();
+}
+
+__attribute__ ((noinline)) static void tail4 () { asm (""); }
+
+NOMIPS16 void k ()
+{
+  tail4 ();
+}
Index: gcc/gcc/testsuite/gcc.target/mips/call-6.c
===================================================================
--- gcc.orig/gcc/testsuite/gcc.target/mips/call-6.c	2016-11-12 10:09:33.658830157 +0000
+++ gcc/gcc/testsuite/gcc.target/mips/call-6.c	2016-11-12 10:09:55.155646930 +0000
@@ -1,5 +1,5 @@ 
 /* Like call-5.c, but for n64.  */
-/* { dg-options "-mrelax-pic-calls -mshared -foptimize-sibling-calls -mabi=64" } */
+/* { dg-options "-mno-micromips -mrelax-pic-calls -mshared -foptimize-sibling-calls -mabi=64" } */
 /* { dg-skip-if "requires -foptimize-sibling-calls" { *-*-* } { "-O0" } { "" } } */
 /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal\n1:\tjalrc?\t" } } */
 /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal2\n1:\tjalrc?\t" } } */
Index: gcc/gcc/testsuite/gcc.target/mips/call-6u.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/gcc/testsuite/gcc.target/mips/call-6u.c	2016-11-12 10:09:55.173844261 +0000
@@ -0,0 +1,52 @@ 
+/* Like call-5.c, but for n64.  */
+/* { dg-options "-mmicromips -mrelax-pic-calls -mshared -foptimize-sibling-calls -mabi=64" } */
+/* { dg-skip-if "requires -foptimize-sibling-calls" { *-*-* } { "-O0" } { "" } } */
+/* { dg-final { scan-assembler "\\.reloc\t1f,R_MICROMIPS_JALR,normal\n1:\tjalrs?\t" } } */
+/* { dg-final { scan-assembler "\\.reloc\t1f,R_MICROMIPS_JALR,normal2\n1:\tjalrs?\t" } } */
+/* { dg-final { scan-assembler "\\.reloc\t1f,R_MICROMIPS_JALR,staticfunc\n1:\tjalrs?\t" } } */
+/* { dg-final { scan-assembler "\\.reloc\t1f,R_MICROMIPS_JALR,tail\n1:\tjalrs?\t" } } */
+/* { dg-final { scan-assembler "\\.reloc\t1f,R_MICROMIPS_JALR,tail2\n1:\tjalrs?\t" } } */
+/* { dg-final { scan-assembler "\\.reloc\t1f,R_MICROMIPS_JALR,tail3\n1:\tjrc?\t" } } */
+/* { dg-final { scan-assembler "\\.reloc\t1f,R_MICROMIPS_JALR,tail4\n1:\tjrc?\t" } } */
+
+__attribute__ ((noinline)) static void staticfunc () { asm (""); }
+int normal ();
+void normal2 ();
+
+int
+NOMIPS16 f (int *p)
+{
+  *p = normal ();
+  normal2 ();
+  staticfunc ();
+  return 1;
+}
+
+int tail ();
+
+int
+NOMIPS16 h ()
+{
+  return tail ();
+}
+
+void tail2 ();
+
+NOMIPS16 void g ()
+{
+  tail2 ();
+}
+
+__attribute__ ((visibility ("hidden"))) void tail3 ();
+
+NOMIPS16 void j ()
+{
+  tail3 ();
+}
+
+__attribute__ ((noinline)) static void tail4 () { asm (""); }
+
+NOMIPS16 void k ()
+{
+  tail4 ();
+}