riscv-collab / v8

Port of Google v8 engine to RISC-V.
https://github.com/v8-riscv/v8/wiki
Other
238 stars 31 forks source link

[HIFIVE] cctest/test-macro-assembler-riscv64/macro_float_minmax_f64 failed #248

Open luyahan opened 3 years ago

luyahan commented 3 years ago

Describe the bug A clear and concise description of what the bug is.

To Reproduce Steps to reproduce the behavior:

  1. Build with options riscv64.native.release
  2. Run test/program ' out/riscv64.native.release/cctest test-macro-assembler-riscv64/macro_float_minmax_f64 --random-seed=-442682909 --nohard-abort --testing-d8-test-runner'
  3. See error

Expected behavior A clear and concise description of what you expected to happen.

Errors/Logs

=== cctest/test-macro-assembler-riscv64/macro_float_minmax_f64 ===
#
# Fatal error in , line 0
# Check failed: bit_cast<uint64_t>(1.0) == bit_cast<uint64_t>(results.max_abc_).
#
#
#
#FailureMessage Object: 0x3fffc88ac8
==== C stack trace ===============================

    /home/luyahan/v8-riscv64/out/riscv64.native.release/cctest(+0x202cf68) [0x2abeee3f68]
    /home/luyahan/v8-riscv64/out/riscv64.native.release/cctest(+0x1fa8394) [0x2abee5f394]
    /home/luyahan/v8-riscv64/out/riscv64.native.release/cctest(+0x1e81d4a) [0x2abed38d4a]
    /home/luyahan/v8-riscv64/out/riscv64.native.release/cctest(+0xddb418) [0x2abdc92418]
    /home/luyahan/v8-riscv64/out/riscv64.native.release/cctest(+0x888098) [0x2abd73f098]
    /home/luyahan/v8-riscv64/out/riscv64.native.release/cctest(+0x80f666) [0x2abd6c6666]
    /lib64/lp64d/libc.so.6(__libc_start_main+0xa6) [0x3fda8ed204]
    /home/luyahan/v8-riscv64/out/riscv64.native.release/cctest(_start+0x2c) [0x2abd73dff8]
Command: out/riscv64.native.release/cctest test-macro-assembler-riscv64/macro_float_minmax_f64 --random-seed=-442682909 --nohard-abort --testing-d8-test-runner
--- FAILED ---

Additional context Add any other context about the problem here.

luyahan commented 3 years ago

I alter code by add volatile for Inputs(volatile Inputs inputs = {src1, src2};) :

  struct Inputs {
    double src1_;
    double src2_;
  };

  struct Results {
    // Check all register aliasing possibilities in order to exercise all
    // code-paths in the macro masm.
    double min_abc_;
    double min_aab_;
    double min_aba_;
    double max_abc_;
    double max_aab_;
    double max_aba_;
  };

  auto f = AssembleCode<F4>(
      GenerateMacroFloat64MinMax<DoubleRegister, Inputs, Results>);

#define CHECK_MINMAX(src1, src2, min, max)                                   \
  do {                                                                       \
    volatile Inputs inputs = {src1, src2};                                   \
    Results results;                                                         \
    f.Call((void*)&inputs, &results, 0, 0, 0);                               \
    CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_abc_)); \
    CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_aab_)); \
    CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_aba_)); \
    CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_abc_)); \
    CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_aab_)); \
    CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_aba_)); \
    /* Use a bit_cast to correctly identify -0.0 and NaNs. */                \
  } while (0)

the case pass. @fw-brice @penguinwu May it be a bug for gcc -o3 ?

luyahan commented 3 years ago

I alter code by add volatile for Inputs(volatile Inputs inputs = {src1, src2};) :

  struct Inputs {
    double src1_;
    double src2_;
  };

  struct Results {
    // Check all register aliasing possibilities in order to exercise all
    // code-paths in the macro masm.
    double min_abc_;
    double min_aab_;
    double min_aba_;
    double max_abc_;
    double max_aab_;
    double max_aba_;
  };

  auto f = AssembleCode<F4>(
      GenerateMacroFloat64MinMax<DoubleRegister, Inputs, Results>);

#define CHECK_MINMAX(src1, src2, min, max)                                   \
  do {                                                                       \
    volatile Inputs inputs = {src1, src2};                                   \
    Results results;                                                         \
    f.Call((void*)&inputs, &results, 0, 0, 0);                               \
    CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_abc_)); \
    CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_aab_)); \
    CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_aba_)); \
    CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_abc_)); \
    CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_aab_)); \
    CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_aba_)); \
    /* Use a bit_cast to correctly identify -0.0 and NaNs. */                \
  } while (0)

the case pass. @fw-brice @penguinwu May it be a bug for gcc -o3 ?

penguinwu commented 3 years ago

Hmm, this test is single-threaded, why would volatile make a difference? Could you take a closer look at the gcc code-gen to see if it can be explained?

luyahan commented 3 years ago

Hmm, this test is single-threaded, why would volatile make a difference? Could you take a closer look at the gcc code-gen to see if it can be explained?

It may be pass the args by a0,a1 but a1 has a wrong value

luyahan commented 3 years ago

Hmm, this test is single-threaded, why would volatile make a difference? Could you take a closer look at the gcc code-gen to see if it can be explained?

i run a test :

#include <iostream>
#include <climits>

struct Inputs {
  double src1_;
  double src2_;
};

double fun(void* a) {
  double r = 0;
  asm ("fld ft0, 8(%1)\n\t"
      "fld ft1, 0(%1)\n\t"
      "fadd.d %0, ft0, ft1\n\t"
      : "=f"(r)
      : "r"(a));
  return r;
}

#define CHECK_MINMAX(src1, src2, min, max)                                   \
  do {                                                                       \
    Inputs inputs = {src1, src2};                                            \
    std::cout << fun((void*)&inputs) << std::endl;                           \
  } while (0)                                                                

int main() {
     CHECK_MINMAX(0.1,0.2,0,0);
     CHECK_MINMAX(0.3,0.9,0,0);
}

It out:

0.1
0.1

but if i add volatile on asm :

#include <iostream>
#include <climits>

struct Inputs {
  double src1_;
  double src2_;
};

double fun(void* a) {
  double r = 0;
  asm volatile("fld ft0, 8(%1)\n\t"
      "fld ft1, 0(%1)\n\t"
      "fadd.d %0, ft0, ft1\n\t"
      : "=f"(r)
      : "r"(a));
  return r;
}

#define CHECK_MINMAX(src1, src2, min, max)                                   \
  do {                                                                       \
    Inputs inputs = {src1, src2};                                            \
    std::cout << fun((void*)&inputs) << std::endl;                           \
  } while (0)                                                                

int main() {
     CHECK_MINMAX(0.1,0.2,0,0);
     CHECK_MINMAX(0.3,0.9,0,0);
}

it out :

0.3
1.2