https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128341

            Bug ID: 128341
           Summary: [AArch64] Trailing debug insns change SME mode-switch
                    insertion point
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Keywords: compare-debug-failure
          Severity: normal
          Priority: P3
         Component: rtl-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: yqtian668 at gmail dot com
  Target Milestone: ---
              Host: x86_64-pc-linux-gnu
            Target: aarch64-unknown-linux-gnu
             Build: x86_64-pc-linux-gnu

Adding debug information changes where GCC inserts the SME lazy-save setup in a
basic block.  On current trunk, -g0 places the add/msr that sets TPIDR2_EL0
before a store, while -g places the same setup after the store.  GCC's own
-fcompare-debug check fails.

I reproduced this with GCC 17.0.0 20261031 (experimental), revision
f1114bb0f3ec67f2fb6bee88f22e148c3d7dedf4, targeting aarch64-unknown-linux-gnu.

Reproducer:

#include <arm_sme.h>

void ext (void);
void ext2 (void) __arm_inout ("za");
int g, h;

__arm_inout ("za") void
f2 (int x)
{
  ext2 ();
  if (x)
    {
      int y = x * 3;
      g = y;
      int z = y + h;
      h = z;
      int w = z * 5;
      (void) w;
    }
  ext ();
  ext2 ();
}

Command:

aarch64-linux-gnu-gcc -O1 -march=armv9-a+sme -ffreestanding \
  -g -fcompare-debug -S source.c

Actual result:

cc1: error: source.c: '-fcompare-debug' failure

The relevant ordinary instructions differ as follows:

-g0:

  add  x2, x29, 32
  msr  tpidr2_el0, x2
  str  w0, [x1, 4]

-g:

  str  w0, [x1, 4]
  add  x0, x29, 32
  msr  tpidr2_el0, x0

Expected result:

Debug information should not change where mode switching inserts the TPIDR2
lazy-save setup.  The -g and -g0 compilations should make the same
code-generation decision.

Cause analysis:

In optimize_mode_switching, a basic block with no mode requirement gets a
seginfo anchored at BB_END (bb).  AArch64 LOCAL_SME_STATE back-propagation
later gives this seginfo the successor's lazy-save mode, and the mode-set
instructions are emitted before the saved anchor.

Without debug information, BB_END is the store to h, so the TPIDR2 setup is
emitted before the store.  With -g, BB_END is a trailing DEBUG_INSN, so the
setup is emitted after the store instead.

A small candidate fix walks backward across only trailing DEBUG_INSNs when
choosing this anchor.  It deliberately does not skip notes, so their existing
placement semantics are preserved.

Verification of the candidate fix on the revision above:

* The focused DejaGNU test fails on the unmodified compiler and passes with the
fix.
* -fcompare-debug passes with the fix.
* Comparing the complete AArch64 SME cross testsuite before and after the
change shows only the new regression test changing from FAIL to PASS; all
pre-existing results are unchanged.
* contrib/check_GNU_style.sh and git diff --check pass.

A full native bootstrap and regression test has not yet been run.

The test case was found by a non-AI automated testing tool.  AI assisted with
the analysis and development of the candidate fix.

Reply via email to