[PATCH 5/6] arm: Fix DWARF register span for Q8-Q15 register variables [PR91381]
Dominic P <[email protected]> Sun, 2 Aug 2026 11:56:07 +0100
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
A 128-bit NEON Q register variable bound to Q8 or above (using the high VFP registers D16-D31) was given an incorrect DWARF location: the two DW_OP_regx operands both named the low D register, e.g. for Q8 DW_OP_regx 272; DW_OP_piece 8; DW_OP_regx 272; DW_OP_piece 8 instead of naming D16 (272) and D17 (273). D16-D31 have no single-precision aliases, so GCC still models each of them as two consecutive 32-bit hard registers. arm_dwarf_register_span built the DImode (D register) pieces stepping the hard register number by one, which selected the same D register twice: arm_debugger_regno maps hard register N to 256 + (N - FIRST_VFP_REGNUM) / 2, so an odd offset rounds down to the previous D register. Step by two so each piece names a distinct D register. Assisted-by: Claude Opus 5 (Anthropic) PR debug/91381 gcc/ChangeLog: * config/arm/arm.cc (arm_dwarf_register_span): Step the DImode pieces for D16-D31 by two hard register numbers. gcc/testsuite/ChangeLog: * gcc.target/arm/pr91381.c: New test. Signed-off-by: Dominic P <[email protected]> --- gcc/config/arm/arm.cc | 7 ++++++- gcc/testsuite/gcc.target/arm/pr91381.c | 26 ++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.target/arm/pr91381.c diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc index 62534baca..71932ee4a 100644 --- a/gcc/config/arm/arm.cc +++ b/gcc/config/arm/arm.cc @@ -30120,9 +30120,14 @@ arm_dwarf_register_span (rtx rtl) } else { + /* D16-D31 (the high VFP registers) have no single-precision aliases, + so GCC still models each of them as two consecutive 32-bit hard + registers. Consecutive DImode (D) registers are therefore spaced + two GCC register numbers apart; stepping by one would describe the + same D register twice (PR debug/91381). */ nregs = GET_MODE_SIZE (mode) / 8; for (i = 0; i < nregs; i++) - parts[i] = gen_rtx_REG (DImode, regno + i); + parts[i] = gen_rtx_REG (DImode, regno + i * 2); } return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nregs , parts)); diff --git a/gcc/testsuite/gcc.target/arm/pr91381.c b/gcc/testsuite/gcc.target/arm/pr91381.c new file mode 100644 index 000000000..fe45e54b9 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr91381.c @@ -0,0 +1,26 @@ +/* PR debug/91381: a 128-bit NEON Q register variable bound to Q8 or above + (D16-D31, which have no single-precision aliases) must describe its two + constituent D registers with distinct DWARF register numbers. Before the + fix the DWARF location repeated the low D register twice, e.g. for Q8: + DW_OP_regx 272; DW_OP_piece 8; DW_OP_regx 272; DW_OP_piece 8. */ + +/* { dg-do compile } */ +/* { dg-require-effective-target arm_neon_ok } */ +/* { dg-options "-g -dA -O0" } */ +/* { dg-add-options arm_neon } */ + +#include <arm_neon.h> + +int +foo (void) +{ + register uint32x4_t q8v asm ("q8") = vdupq_n_u32 (0); + __asm__ __volatile__ ("" : : "w" (q8v)); + return 0; +} + +/* Q8 == D16:D17, whose DWARF register numbers are 272 (0x110) and 273 (0x111). + The low D register (0x110) must be described once and the high D register + (0x111) once; the buggy output emitted 0x110 twice and never 0x111. */ +/* { dg-final { scan-assembler-times "uleb128 0x110\[^0-9a-f\]" 1 } } */ +/* { dg-final { scan-assembler-times "uleb128 0x111\[^0-9a-f\]" 1 } } */ -- 2.55.0