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.