mips16_gp_pseudo_reg emits the $gp load in the topmost sequence before
its first real insn.  The scan skips CODE_LABELs, so the load can land
in a later block, and since r16-1398 that block can be expanded but not
BB_RTL yet, where add_insn_after crashes on BB_END.

Emit the load and the clobbers after entry_of_function () instead, as
other ports do.  Before construct_init_block that is not usable, but
the topmost sequence then only holds the parameter setup, so emit
after its first insn.  The entry edge does not work: pass_expand puts
those insns after the parameter setup, which can itself use $gp.

Assisted-by: Claude:claude-opus-5-5

        PR target/125582

gcc/ChangeLog:

        * config/mips/mips.cc (mips16_gp_pseudo_reg): Emit the $gp load
        and the clobbers after entry_of_function (), or after the first
        insn before the init block exists.

gcc/testsuite/ChangeLog:

        * gcc.target/mips/pr125582.c: New test.

Suggested-by: Jakub Jelinek <[email protected]>
Signed-off-by: Julius Bairaktaris <[email protected]>
---
v2: Fix it in mips16_gp_pseudo_reg as Jakub suggested, instead of in
add_insn_after/add_insn_before.

Tested with a mipsel-linux-musl cross compiler, binutils and qemu-user,
compared with unpatched master:

- gcc.target/mips/mips.exp: no regressions.  Fixes the new test and
  gcc.target/mips/pr59317.c, which ICEs on master.
- gcc.c-torture/execute and compile with -mips16 -mabicalls -fpic
  -static: no regressions, 2480 -> 17 failures.
- gcc.c-torture/execute with -mips16 -minterlink-mips16 -mabicalls
  -fPIC -static: no regressions, 1799 -> 5 failures.

The remaining failures fail the same way without the patch.

 gcc/config/mips/mips.cc                  | 18 ++++++++---------
 gcc/testsuite/gcc.target/mips/pr125582.c | 25 ++++++++++++++++++++++++
 2 files changed, 34 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/mips/pr125582.c

diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc
index e54a310b2b4..3ff5e9ef500 100644
--- a/gcc/config/mips/mips.cc
+++ b/gcc/config/mips/mips.cc
@@ -3400,18 +3400,11 @@ mips16_gp_pseudo_reg (void)
 {
   if (cfun->machine->mips16_gp_pseudo_rtx == NULL_RTX)
     {
-      rtx_insn *scan;
-
       cfun->machine->mips16_gp_pseudo_rtx = gen_reg_rtx (Pmode);
 
-      push_topmost_sequence ();
-
-      scan = get_insns ();
-      while (NEXT_INSN (scan) && !INSN_P (NEXT_INSN (scan)))
-       scan = NEXT_INSN (scan);
-
+      start_sequence ();
       rtx set = gen_load_const_gp (cfun->machine->mips16_gp_pseudo_rtx);
-      rtx_insn *insn = emit_insn_after (set, scan);
+      rtx_insn *insn = emit_insn (set);
       INSN_LOCATION (insn) = 0;
       /* NewABI support hasn't been implement.  NewABI should generate RTL
         sequence instead of ASM sequence directly.  */
@@ -3420,6 +3413,13 @@ mips16_gp_pseudo_reg (void)
          emit_clobber (MIPS16_PIC_TEMP);
          emit_clobber (MIPS_PROLOGUE_TEMP (Pmode));
        }
+      rtx_insn *seq = end_sequence ();
+
+      /* Until construct_init_block, the topmost sequence is just the
+        parameter setup, all of which goes into the init block.  */
+      push_topmost_sequence ();
+      emit_insn_after (seq, (ENTRY_BLOCK_PTR_FOR_FN (cfun)->flags & BB_RTL
+                            ? entry_of_function () : get_insns ()));
       pop_topmost_sequence ();
     }
 
diff --git a/gcc/testsuite/gcc.target/mips/pr125582.c 
b/gcc/testsuite/gcc.target/mips/pr125582.c
new file mode 100644
index 00000000000..524ef4bdf4d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/pr125582.c
@@ -0,0 +1,25 @@
+/* PR target/125582 */
+/* { dg-do compile } */
+/* { dg-options "-mabicalls -fpic -mips16" } */
+
+int foo (void *, unsigned, unsigned);
+
+static int
+bar (int *p)
+{
+  int ret;
+
+  do
+    ret = foo (p, sizeof (*p), 1);
+  while (ret == -1);
+
+  return ret;
+}
+
+int
+baz (void)
+{
+  int x = 1;
+
+  return bar (&x);
+}
-- 
2.53.0

Reply via email to