Re: arm64, valgrind floating point instruction produces different result
Am 26.06.24 um 21:31 schrieb Jeffrey Walton:
Is there some knowledge about such an issue, or how to avoid this?
[1071656] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1071656
I'm not sure if it matters, but Valgrind added support for the fcvtas
using the following register types. See
<https://valgrind.org/docs/manual/dist.news.old.html> and
<https://bugs.kde.org/show_bug.cgi?id=340509>.
fcvtas w12, s1
I think the difference between dN (your example) and sN (valgrind)
register are bit widths. dN is 32-bit, and sN is 16-bit.
(This may be a rabbit hole).
Jeff
Hello Jeff,
thanks for this information.
That sounds like this might be just a plain bug in valgrind?
(And my thinking of how valgrind works was quite wrong.)
I tried to take a look and I guess one interesting part is in [1],
where the fcvtas gets translated into the immediate representation
with a rounding mode `Irrm_NEAREST`, the same as fcvtns.
In [2] is another "rounding mode conversion" and in [3] it looks
like it gets translated back to an instruction for the real
execution in the cpu, but unfortunately this is maybe a fcvtns,
which therefore does not return the desired value.
Valgrind's intermediate representation knows another rounding
mode Irrm_NEAREST_TIE_TOWARD_0 which may fit the fcvtas better,
but it looks like this gets no translation in [2].
So I guess the best would be to simply report it to the
valgrind bug tracker now?
Kind regards,
Bernhard
[1] https://sourceware.org/git/?p=valgrind.git;a=blob;f=VEX/priv/guest_arm64_toIR.c;h=c3957bf58b269c1863d7246865f5ba6225bad3ca;hb=HEAD#l15940
[2] https://sourceware.org/git/?p=valgrind.git;a=blob;f=VEX/priv/host_arm64_isel.c;h=645358586f3459d885506512277221cfa1909871;hb=HEAD#l1925
[3] https://sourceware.org/git/?p=valgrind.git;a=blob;f=VEX/priv/host_arm64_defs.c;h=0b59c87cd3bddf3cb8374414cd8e065c660926a3;hb=HEAD#l4459
[4]
benutzer@chroot-13-trixie-unstable:~$ gcc -g -O2 fp-valgrind-test.c -o fp-valgrind-test
benutzer@chroot-13-trixie-unstable:~$ ./fp-valgrind-test
i=0 a=-322.500001 a=0xc0742800010c6f7a b=-323
i=1 a=-322.500000 a=0xc074280000000000 b=-323 <<<
i=2 a=-322.499999 a=0xc07427fffef39086 b=-322
i=3 a=322.499999 a=0x407427fffef39086 b=322
i=4 a=322.500000 a=0x4074280000000000 b=323 <<<
i=5 a=322.500001 a=0x40742800010c6f7a b=323
benutzer@chroot-13-trixie-unstable:~$ valgrind ./fp-valgrind-test
==35570== Memcheck, a memory error detector
==35570== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==35570== Using Valgrind-3.20.0 and LibVEX; rerun with -h for copyright info
==35570== Command: ./fp-valgrind-test
==35570==
i=0 a=-322.500001 a=0xc0742800010c6f7a b=-323
i=1 a=-322.500000 a=0xc074280000000000 b=-322 <<<
i=2 a=-322.499999 a=0xc07427fffef39086 b=-322
i=3 a=322.499999 a=0x407427fffef39086 b=322
i=4 a=322.500000 a=0x4074280000000000 b=322 <<<
i=5 a=322.500001 a=0x40742800010c6f7a b=323
==35570==
/*
cat fp-valgrind-test.c
gcc -g -O2 fp-valgrind-test.c -o fp-valgrind-test
./fp-valgrind-test
valgrind ./fp-valgrind-test
gdb -q --args ./fp-valgrind-test
disassemble main
q
*/
#include <stdio.h>
#include <math.h>
double __attribute__((optimize("O0"))) value(int s)
{
switch (s) {
case 0: return -322.500001; break;
case 1: return -322.5; break;
case 2: return -322.499999; break;
case 3: return 322.499999; break;
case 4: return 322.5; break;
default: return 322.500001; break;
}
}
int main()
{
for (int i = 0; i < 6; i++) {
double a = value(i);
int b = (int)round(a);
printf("i=%d a=%f a=0x%llx b=%d\n", i, a, *(long long unsigned int*)&a, b);
}
}
Reply to: