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
everything after the first insn of the topmost sequence then becomes
the init block, so emit after that insn.  The current sequence does not
work there: expand_phi_nodes can call this while emitting the copies
for one PHI edge.  The entry edge does not work either: 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]>
---
v3: Name expand_phi_nodes in the comment and the commit message.  The
code is unchanged from v2, so the v2 testing still applies:

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                  | 19 +++++++++---------
 gcc/testsuite/gcc.target/mips/pr125582.c | 25 ++++++++++++++++++++++++
 2 files changed, 35 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..dc25c849bff 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,14 @@ 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, everything after the first insn of
+        the topmost sequence becomes the init block.  The current sequence
+        can then be the copies on one PHI edge from expand_phi_nodes.  */
+      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