[valgrind] [Bug 523962] New: On armhf, memcheck with --track-origins=yes reports fully initialised NEON output as undefined

Alireza <[email protected]>
Newsgroups gmane.comp.kde.devel.bugs
Message-ID <[email protected]/>
https://bugs.kde.org/show_bug.cgi?id=523962

            Bug ID: 523962
           Summary: On armhf, memcheck with --track-origins=yes reports
                    fully initialised NEON output as undefined
    Classification: Developer tools
           Product: valgrind
      Version First 3.24.0
       Reported In:
          Platform: Debian stable
                OS: Linux
            Status: REPORTED
          Severity: normal
          Priority: NOR
         Component: vex
          Assignee: [email protected]
          Reporter: [email protected]
  Target Milestone: ---

Created attachment 194937
  --> https://bugs.kde.org/attachment.cgi?id=194937&action=edit
reproduction sample

DESCRIPTION
Without --track-origins=yes the issue is gone. This was first discovered during
valgrind runs on libvpx, and it still exists on latest HEAD, even though
reproduction steps here are for 3.24.0.

DISCLAIMER: To produce an isolated reproduction from the libvpx decoding
scenario that was encountered, an LLM was used.

STEPS TO REPRODUCE
1. Run docker image and mount repro file: `docker run -it --rm --platform
linux/arm/v7 -v ./repro.c:/root/repro.c:z arm32v7/debian:trixie`
2. Install valgrind + gcc in image: `apt-get update && apt-get install -y gcc
libc6-dev valgrind`
3. Build repro: `gcc -O2 -g -march=armv7-a -mfpu=neon -mfloat-abi=hard
/root/repro.c -o /root/repro`
4. Run valgrind with track-origins: `valgrind --tool=memcheck -q
--track-origins=yes /root/repro`

OBSERVED RESULT
```
==10194== Conditional jump or move depends on uninitialised value(s)
==10194==    at 0x108582: main (repro.c:84)
==10194== 
==10194== 
==10194== HEAP SUMMARY:
==10194==     in use at exit: 0 bytes in 0 blocks
==10194==   total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==10194== 
==10194== All heap blocks were freed -- no leaks are possible
==10194== 
==10194== For lists of detected and suppressed errors, rerun with: -s
==10194== ERROR SUMMARY: 8 errors from 1 contexts (suppressed: 77 from 76)
```

EXPECTED RESULT

The same command without `--track-origins` has no errors
```
==10199== HEAP SUMMARY:
==10199==     in use at exit: 0 bytes in 0 blocks
==10199==   total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==10199== 
==10199== All heap blocks were freed -- no leaks are possible
==10199== 
==10199== For lists of detected and suppressed errors, rerun with: -s
==10199== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 77 from 76)
```

ADDITIONAL INFORMATION

According to the LLM:
> ARMin_NUnaryS/ARMneon_SETELEM lowers to vmov.32 dD[i], rS, which writes a single 32-bit lane and must preserve the other. getRegUsage_ARMInstr declares the destination write-only, so the allocator treats the previous contents as dead: it spills the vreg the SETELEM is meant to modify, never reloads it, and emits the in-place lane write anyway. The surviving lane keeps unrelated data. Where the affected vreg is a memcheck V-shadow, those leftovers read as "undefined".

> Origin tracking is only the trigger - it roughly doubles the instrumentation, which lengthens live ranges until a spill lands between the two lane inserts.

The LLM also generated a fix. While it resolves the issue I can't confirm there
won't be other regressions. It might be helpful so I'll include it anyway:
```
diff --git a/VEX/priv/host_arm_defs.c b/VEX/priv/host_arm_defs.c
--- a/VEX/priv/host_arm_defs.c
+++ b/VEX/priv/host_arm_defs.c
@@ -2375,6 +2375,13 @@ static void getRegUsage_ARMInstr ( HRegUsage* u, const
ARMInstr* i, Bool mode64
          return;
       case ARMin_NUnaryS:
          addHRegUse(u, HRmWrite, i->ARMin.NUnaryS.dst->reg);
+         if (i->ARMin.NUnaryS.op == ARMneon_SETELEM) {
+            /* SETELEM writes only the selected lane of dst; the other
+               lanes must be preserved.  So dst is modified, not merely
+               written, and the reg-allocator must reload it if it has
+               been spilled. */
+            addHRegUse(u, HRmRead, i->ARMin.NUnaryS.dst->reg);
+         }
          addHRegUse(u, HRmRead, i->ARMin.NUnaryS.src->reg);
          return;
       case ARMin_NShift:
```

-- 
You are receiving this mail because:
You are watching all bug changes.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.