On Wed, 7 Oct 2026, Julius Bairaktaris wrote:

> Since r16-1398, expanded blocks stay non-BB_RTL until the end of
> expansion, but BLOCK_FOR_INSN of their insns is already set.
> mips16_gp_pseudo_reg emits the $gp load after the basic block note of
> such a block, and add_insn_after then crashes on BB_END.  Only touch
> BB_END and BB_HEAD of BB_RTL blocks; pass_expand::execute sets them
> for the others from head_end_for_bb.

Hmm, I think this issue might be more wide-spread and using arbitrary
RTL APIs during RTL expansion is now dangerous.  That said,
mips16_gp_pseudo_reg should probably not do this, since try-expansion
and throw away is expected to leave no trail.

How do we get there?

> Assisted-by: Claude:claude-opus-5-5
> 
>       PR target/125582
> 
> gcc/ChangeLog:
> 
>       * emit-rtl.cc (add_insn_after): Only update BB_END for BB_RTL
>       blocks.
>       (add_insn_before): Only check BB_HEAD for BB_RTL blocks.
> 
> gcc/testsuite/ChangeLog:
> 
>       * gcc.target/mips/pr125582.c: New test.
> 
> Signed-off-by: Julius Bairaktaris <[email protected]>
> ---
> Bootstrapped and regtested on x86_64-pc-linux-gnu with no new failures.
> gcc.target/mips/mips.exp on a mipsel-linux-musl cross compiler shows no
> changes except the new test, which ICEs at -O1 and above without the
> patch.
> 
>  gcc/emit-rtl.cc                          |  9 ++++++---
>  gcc/testsuite/gcc.target/mips/pr125582.c | 25 ++++++++++++++++++++++++
>  2 files changed, 31 insertions(+), 3 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/mips/pr125582.c
> 
> diff --git a/gcc/emit-rtl.cc b/gcc/emit-rtl.cc
> index d064b2a1064..06294604573 100644
> --- a/gcc/emit-rtl.cc
> +++ b/gcc/emit-rtl.cc
> @@ -4373,8 +4373,10 @@ add_insn_after (rtx_insn *insn, rtx_insn *after, 
> basic_block bb)
>        if (INSN_P (insn))
>       df_insn_rescan (insn);
>        /* Should not happen as first in the BB is always
> -      either NOTE or LABEL.  */
> -      if (BB_END (bb) == after
> +      either NOTE or LABEL.  Blocks expanded but not yet BB_RTL
> +      have no BB_END.  */
> +      if ((bb->flags & BB_RTL)
> +       && BB_END (bb) == after
>         /* Avoid clobbering of structure when creating new BB.  */
>         && !BARRIER_P (insn)
>         && !NOTE_INSN_BASIC_BLOCK_P (insn))
> @@ -4408,7 +4410,8 @@ add_insn_before (rtx_insn *insn, rtx_insn *before, 
> basic_block bb)
>       df_insn_rescan (insn);
>        /* Should not happen as first in the BB is always either NOTE or
>        LABEL.  */
> -      gcc_assert (BB_HEAD (bb) != insn
> +      gcc_assert (!(bb->flags & BB_RTL)
> +               || BB_HEAD (bb) != insn
>                 /* Avoid clobbering of structure when creating new BB.  */
>                 || BARRIER_P (insn)
>                 || NOTE_INSN_BASIC_BLOCK_P (insn));
> 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);
> +}
> 

-- 
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Stefan Gaiser, Jochen Jaser, Abhinav Puri; (HRB 36809, AG Nuernberg)

Reply via email to