Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

one question about nanf process #1092

Closed
unicornx opened this issue Jun 16, 2022 · 4 comments
Closed

one question about nanf process #1092

unicornx opened this issue Jun 16, 2022 · 4 comments

Comments

@unicornx
Copy link

Case A:

char buf[BUFSIZ];
snprintf(buf, sizeof(buf), "[%a]", -nanf(""));

Case B:

char buf[BUFSIZ];
snprintf(buf, sizeof(buf), "[%a]", -nanf("hello"));

When I compile these two code segments with riscv64-gcc(11.0 and 13.0 both), I find different behavior and result.

For case A, gcc will use a constant value of -NaN, but not call nanf(), equal to "snprintf(buf, sizeof(buf), "[%a]", -NAN);" and we can get "-nan" in buf[].

For case B, gcc will call nanf() but this makes the snprintf() print buf[] as "nan". It's not expected. I disassemble the code and find the problem is caused by an instruction of fcvt.d.s

10600:       20a507d3               fmv.s   fa5,fa0
10604:       20f797d3                fneg.s  fa5,fa5
10608:       420787d3               fcvt.d.s  fa5,fa5

fa0 stores return value from nanf() and it is 0xfffff7fc00000, I think it is correct, it is NAN in single float.
in line 10604, fa5 is given 0xfffffffc00000, it is -NAN in single float, I think it is no problem.
but in line 10608, fcvt.d.s convert 0xfffffffc00000 to 0x7ff8000000000000, and the sign bit is zero and lost the negative. Note I am running this on QEMU(tried 6.2 and 7.0 both the same result)

I wonder

  • Does gcc do optimization for Case A?
  • Why case A and case B behave different?
  • I think case B is wrong, what's the root-cause ?

Thanks a lot.

@unicornx
Copy link
Author

hello, who can help answer this, thanks.

@FantasqueX
Copy link

Hi, I met the same issue when testing glibc. The full analysis is recorded in felixonmars/archriscv-packages#1704.

TLDR, strfromf converts -NAN with type float to double first. After the conversion, the variable becomes NAN.

I think the root cause can be found in chapter 11.3 of riscv-spec-20191213,

Except when otherwise stated, if the result of a floating-point operation is NaN, it is the canonical NaN. The canonical NaN has a positive sign and all significand bits clear except the MSB, a.k.a. the quiet bit. For single-precision floating-point, this corresponds to the pattern 0x7fc00000.

which means that conversion -NAN from float to double won't keep the signbit.

I think this case wrong as well. Other architecture does keep the signbit when converting. As for solution, I don't know how to deal with it :(

@unicornx
Copy link
Author

unicornx commented Sep 16, 2022

@FantasqueX I have found the rootcause of case A is due to gcc implements nanf by builtin function and this will convert the calling of nanf("") with const value by default. As for case B, I think the behavior is correct and meets requirement from riscv spec. But anyway, it's just from my personal point of view, just for your reference.

That's why I have not close this issue and am looking for more input from professional person.

@TommyMurphyTM1234
Copy link
Collaborator

No activity in over a year and if the issue is valid then it should probably be logged in the relevant upstream project (GCC, Glibc, Newlib?) rather than here on riscv-gnu-toolchain. As such I am closing the issue here.

@TommyMurphyTM1234 TommyMurphyTM1234 closed this as not planned Won't fix, can't repro, duplicate, stale Oct 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants