Issue 167376
Summary Miscomparison of signed-zeros
Labels new issue
Assignees
Reporter tuliom
    A [recent PR](https://github.com/llvm/llvm-test-suite/pull/273) to llvm-test-suite enabled test `fmax-reduction`.
This test was getting skipped before this PR got merged.

After that, we started seeing this test to fail on all architectures supported by Fedora with the following error:

```
FAIL: test-suite :: SingleSource/UnitTests/Vectorizer/fmax-reduction.test (2384 of 2423)
******************** TEST 'test-suite :: SingleSource/UnitTests/Vectorizer/fmax-reduction.test' FAILED ********************

/var/tmp/llvm-test-suite.kwn8stIzGS/tools/timeit-target --timeout 7200 --limit-core 0 --limit-cpu 7200 --limit-file-size 209715200 --limit-rss-size 838860800 --append-exitstatus --redirect-output /var/tmp/llvm-test-suite.kwn8stIzGS/SingleSource/UnitTests/Vectorizer/Output/fmax-reduction.test.out --redirect-input /dev/null --chdir /var/tmp/llvm-test-suite.kwn8stIzGS/SingleSource/UnitTests/Vectorizer --summary /var/tmp/llvm-test-suite.kwn8stIzGS/SingleSource/UnitTests/Vectorizer/Output/fmax-reduction.test.time /var/tmp/llvm-test-suite.kwn8stIzGS/SingleSource/UnitTests/Vectorizer/fmax-reduction
/var/tmp/llvm-test-suite.kwn8stIzGS/tools/fpcmp-target /var/tmp/llvm-test-suite.kwn8stIzGS/SingleSource/UnitTests/Vectorizer/Output/fmax-reduction.test.out /var/tmp/llvm-test-suite.kwn8stIzGS/SingleSource/UnitTests/Vectorizer/fmax-reduction.reference_output

+ /var/tmp/llvm-test-suite.kwn8stIzGS/tools/fpcmp-target /var/tmp/llvm-test-suite.kwn8stIzGS/SingleSource/UnitTests/Vectorizer/Output/fmax-reduction.test.out /var/tmp/llvm-test-suite.kwn8stIzGS/SingleSource/UnitTests/Vectorizer/fmax-reduction.reference_output
/var/tmp/llvm-test-suite.kwn8stIzGS/tools/fpcmp-target: Comparison failed, textual difference between 'M' and 'C'

Input 1:
Checking fmaxnum_start_neg_2
Miscompare signed-zeros: -0 != 0
exit 1

Input 2:
Checking fmaxnum_start_neg_2
Checking fmaxnum_start_min
Checking fmaxnum_start_denorm_min
Checking fmaxnum_start_is_nan
Checking fmax_strict_start_neg_2
Checking fmax_strict_start_min
Checking fmax_strict_start_denorm_min
Checking fmax_strict_start_nan
Checking fmax_non_strict_start_neg_2
Checking fmax_cmp_max_gt_start_neg_2
Checking fmax_cmp_max_lt_start_neg_2
Checking fmax_cmp_max_lt_start_denorm_min
Checking fmax_cmp_max_lt_start_neg_nan
exit 0
```

I reduced the test to:
```
#include <algorithm>
#include <functional>
#include <iostream>
#include <limits>
#include <memory>
#include <stdint.h>

#include "common.h"

static bool isEqual(float A, float B) {
  if (std::isnan(A) || std::isnan(B))
    return std::isnan(A) && std::isnan(B);

  if (A == 0.0f)
    return B == 0.0f && std::signbit(A) == std::signbit(B);

  return A == B;
}

template <typename Ty> using Fn1Ty = std::function<Ty(Ty *, unsigned)>;

template <typename Ty>
static void check(Fn1Ty<Ty> ScalarFn, Fn1Ty<Ty> VectorFn, float *Src,
 unsigned N, const char *Type) {
  auto Reference = ScalarFn(Src, N);
 auto ToCheck = VectorFn(Src, N);
  if (!isEqual(Reference, ToCheck)) {
 std::cerr << "Miscompare " << Type << ": " << Reference << " != " << ToCheck
              << "\n";
    exit(1);
  }
}

template <typename Ty>
static void checkVectorFunction(Fn1Ty<Ty> ScalarFn, Fn1Ty<Ty> VectorFn,
                                const char *Name) {
  std::cout << "Checking " << Name << "\n";

  unsigned N = 1024;
 std::unique_ptr<Ty[]> Src1(new Ty[N]);
  init_data(Src1, N);

  // Check with multiple signed-zeros at different positions.
  for (unsigned Idx = 0; Idx != 64; ++Idx) {
    for (unsigned I = 0; I != N; ++I)
      Src1[I] = -1.0;

    for (unsigned Offset = 1; Offset != 32; ++Offset) {
 Src1[Idx] = -0.0;
      Src1[Idx + Offset] = +0.0;

      check(ScalarFn, VectorFn, &Src1[0], N, "signed-zeros");
    }
  }

  for (unsigned Idx = 0; Idx != 64; ++Idx) {
    for (unsigned I = 0; I != N; ++I)
 Src1[I] = -1.0;

    for (unsigned Offset = 1; Offset != 32; ++Offset) {
 Src1[Idx] = +0.0;
      Src1[Idx + Offset] = -0.0;

 check(ScalarFn, VectorFn, &Src1[0], N, "signed-zeros");
    }
 }
}

int main(void) {
  {
    DEFINE_SCALAR_AND_VECTOR_FN1_TYPE(
 float Max = -2.0;, for (unsigned I = 0; I < 1024;
 I++) { Max = std::fmax(Max, A[I]); } return Max;
        , float);
 checkVectorFunction<float>(ScalarFn, VectorFn, "fmaxnum_start_neg_2");
 }

  return 0;
}
```

I can reproduce it with the following command:
```
$ clang++  -O1 ./fmax-reduction.cpp -o fmax-reduction -lstdc++ -lm && ./fmax-reduction
Checking fmaxnum_start_neg_2
Miscompare signed-zeros: -0 != 0
```

I bisected this issue to commit 004c67ea257039e4e98abc26dd4ac6e8f3d7a171 (PR #148239).
Heads up: this commit has been backported to LLVM 21.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to