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)
gcc/ChangeLog:
PR target/91381
* config/arm/arm.cc (arm_dwarf_register_span): Step the DImode
pieces for D16-D31 by two hard register numbers.
gcc/testsuite/ChangeLog:
PR target/91381
* gcc.target/arm/pr91381.c: New test.
Signed-off-by: Dominic P <[email protected]>
---
Changes in v2:
- drop the five-line comment v1 added to arm_dwarf_register_span; it repeats
the commit message, and you asked for exactly that when you pushed 2/6 of
this series.
- cut the test's header comment to one sentence.
- ChangeLog: PR target/91381, in the per-file blocks as in 1/6 and 4/6 --
the bug was re-componented from debug to target on 4 Sep.
The one code line is unchanged. Still reproduces on trunk 2cb78d1a0e5: for a
uint32x4_t bound to q8, -g -O0 -mfpu=neon -mfloat-abi=softfp -march=armv7-a
emits .uleb128 0x110 twice and 0x111 never; with the patch, each once.
Retested on arm-none-eabi against a pristine build of that commit, arm.exp
mve.exp simd.exp on the default board and on an arm-linux-gnueabihf-like board
(-mthumb -mfloat-abi=hard -mtune=cortex-a9 -march=armv7-a -mfpu=neon-fp-armv8):
no test changes status on either, and pr91381.c is the only addition.
OK for trunk?
gcc/config/arm/arm.cc | 2 +-
gcc/testsuite/gcc.target/arm/pr91381.c | 23 +++++++++++++++++++++++
2 files changed, 24 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 33b64995442..cb2141186ea 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -30121,7 +30121,7 @@ arm_dwarf_register_span (rtx rtl)
{
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 00000000000..2c6b76aac4b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr91381.c
@@ -0,0 +1,23 @@
+/* PR target/91381: a Q8-Q15 register variable must name two distinct D
+ registers. */
+
+/* { 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