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

            Bug ID: 127460
           Summary: [PRU] Debug information causes an extra repeat-loop
                    NOP with -fno-var-tracking
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: yqtian668 at gmail dot com
  Target Milestone: ---

Created attachment 65622
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65622&action=edit
source c file to trigger this bug

I see one additional ordinary NOP in PRU repeat-loop code when compiling the
same source with `-g -fno-var-tracking` instead of `-g0 -fno-var-tracking`.
The difference reproduces on current GCC master revision
`11ae0ce305601ebf85b1a09b130cb3e7b46157f9`.

Test case (`source.c`, also attached):

```c
unsigned int
test_loop (unsigned int n, unsigned int x)
{
  unsigned int i;

  if (n >= 0x10000)
    return 0;
  if (!n)
    return 0;

  for (i = 0; i < n; i++)
    x <<= 2;
  return x;
}
```

Commands:

```text
xgcc -B/path/to/gcc -O1 -mloop -S -Wall -Wextra \
  -fno-var-tracking -g0 source.c -o g0.s

xgcc -B/path/to/gcc -O1 -mloop -S -Wall -Wextra \
  -fno-var-tracking -g source.c -o g.s
```

Both commands exit successfully with no diagnostics. The only difference in
the ordinary instruction sequence is the extra NOP:

```diff
 loop .L7, r14
 lsl r15, r15, 2
 nop
+nop
 mov r14, r15
 ret
```

I repeated the pair five times on an unmodified build. Every `-g0` compilation
emitted one NOP and every `-g` compilation emitted two. Removing NOPs makes the
remaining ordinary instruction sequences identical.

Expected result: adding debug information should not change the number of
ordinary padding instructions in the repeat loop.

The difference requires `-fno-var-tracking`. With GCC's default variable
tracking, the `-g0` and `-g` ordinary instruction sequences are identical and
both contain one NOP. Disabling only variable-tracking assignments also does
not trigger the difference:

```text
options                              -g0 NOPs   -g NOPs
default                                  1          1
-fno-var-tracking                        1          2
-fno-var-tracking-assignments            1          1
both options disabled                    1          2
```

The apparent cause is in `pru_insert_loop_label_last` in
`gcc/config/pru/pru.cc`. Its backward scan counts the last two recognized
opcodes, but it sends every `INSN_P` member to `recog_memoized`. A surviving
`DEBUG_INSN` has a negative recognition code, so the scan stops before counting
the preceding ordinary opcode and inserts one additional NOP. This paragraph
is cause analysis; the emitted assembly difference above is the directly
observed result.

Compiler information:

```text
Using built-in specs.
COLLECT_GCC=/build/gcc/xgcc
Target: pru-unknown-elf
Configured with: /source/configure --target=pru-unknown-elf \
  --disable-bootstrap --disable-multilib --disable-nls \
  --enable-languages=c --without-headers --disable-werror
Thread model: single
Supported LTO compression algorithms: zlib zstd
gcc version 17.0.0 20260918 (experimental) (GCC)
```

Build host: x86_64 GNU/Linux, Ubuntu 24.04.4 LTS, Linux 5.15.0-153-generic.

Reply via email to