Undefined compiler behaviour or a compiler bug?

Mehmet Erol Sanliturk m.e.sanliturk at gmail.com
Thu Apr 29 22:31:04 UTC 2021


On Fri, Apr 30, 2021 at 12:08 AM Hans Petter Selasky <hps at selasky.org>
wrote:

> Hi,
>
> Can someone please explain what C-compiler flag I'm missing, to make
> this simple C-program terminate?
>
> I have a function _abs() which at some point is equal to one, but the
> compiler thinks it is not required to emit the test for the while() at
> all, looking at the assembly code! A printf() clearly verifies that the
> _abs() function has returned one.
>
> I even added an own if() check, but apparently the compiler is lost!
>
> cat << EOF > test.c
> #include <stdio.h>
> #include <stdint.h>
>
> typedef struct {
>         int32_t x;
>         int32_t y;
> } c32_t;
>
> static c32_t
> _mul(c32_t a, c32_t b)
> {
>         return (c32_t){
>                 a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x
>         };
> }
>
> static uint32_t
> _abs(c32_t a)
> {
>         return (a.x * a.x + a.y * a.y);
> }
>
> int
> main()
> {
>         c32_t a = {4, 1};
>         c32_t b = {};
>         uint32_t l1 = 0;
>
>         while (_abs(a) != 1) {
>                 uint32_t l0 = _abs(a) & ~1;
>
>                 /* figure out least significant bit */
>                 l0 &= ~(l0 - 1);
>
>                 if (l0 == 0 || l0 > l1) {
>                         l1 = l0;
>                         if (_abs(a) == 1)
>                                 printf("VALUE IS ONE\n");
>                         printf("Y:0x%08x ABS:0x%08x\n", a.y, _abs(a));
>                 }
>                 a.y += 2;
>         }
>
>         size_t count = 0;
>
>         do {
>                 count++;
>                 b = _mul(b, a);
>         } while (b.x != 1 || b.y != 0);
>
>         printf("%d,%d,0x%x COUNT=%zd\n", a.x, a.y, _abs(a), count);
>
>         return (0);
> }
> EOF
>
> clang11 -O2 test.c && ./a.out
>
> --HPS
> _______________________________________________
>
>

If  _abs(a) is not an Integer , please do NOT use " equality" comparison
with Integer 1 .
Instead , please use  "If     abs ( ( _abs(a) - 1 ) ) is 'less than or
equal to an Epsilon approximate to Zero'  " , because equality of a
floating point value to an integer value is approximately  "Impossible" due
to trailing bits unpredictability of floating point values .

And do not rely on "printed  values" of "floating point" values , because
a value in memory and its printed values approximately are always different
due to formatting specification .


Mehmet Erol Sanliturk


More information about the freebsd-current mailing list