[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: