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 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 (); +}