This is an archive of the discontinued LLVM Phabricator instance.

[libc] Generate math.h instead of the static file it is currently.
ClosedPublic

Authored by sivachandra on Mar 24 2020, 12:24 PM.

Details

Summary

Just enough to help a follow up patch adding cosf and sinf has been
added.

Diff Detail

Event Timeline

sivachandra created this revision.Mar 24 2020, 12:24 PM
abrachet added inline comments.Mar 24 2020, 12:55 PM
libc/config/linux/api.td
113

__builtin_nanf() takes a const char * argument. I have no idea why. https://github.com/llvm/llvm-project/blob/master/clang/lib/AST/ExprConstant.cpp#L12816

libc/spec/stdc.td
181–185

Should we include these even though we have no implementation of them?

  • Add "" arg to __builtin_nanf.
  • Remove cosf and sinf from linux API; will add them in the patch adding their implementation.
sivachandra marked 2 inline comments as done.Mar 24 2020, 2:30 PM
sivachandra added inline comments.
libc/spec/stdc.td
181–185

Good point. Will add them in the patch adding their implementation.

abrachet accepted this revision.Mar 24 2020, 2:56 PM
This revision is now accepted and ready to land.Mar 24 2020, 2:56 PM
This revision was automatically updated to reflect the committed changes.
PaulkaToast added inline comments.
libc/config/linux/api.td
79

I think some of this might be gcc/glibc specific stuff and should be thought over. See:

0 is actually not a value allowed by the C2011 standard for math_errhandling. See this excerpt:

The macros
MATH_ERRNO
MATH_ERREXCEPT
expand to the integer constants 1 and 2, respectively; the macro
math_errhandling expands to an expression that has type int and the value
MATH_ERRNO, MATH_ERREXCEPT, or the bitwise OR of both.

For all functions, a domain error occurs if an input argument is outside the domain over
which the mathematical function is defined. The description of each function lists any
required domain errors; an implementation may define additional domain errors, provided
that such errors are consistent with the mathematical definition of the function.228) On a
domain error, the function returns an implementation-defined value; if the integer
expression math_errhandling & MATH_ERRNO is nonzero, the integer expression
errno acquires the value EDOM; if the integer expression math_errhandling & MATH_ERREXCEPT
is nonzero, the ‘‘invalid’’ floating-point exception is raised.

__NO_MATH_ERRNO__ in particular is very gcc specific and clang doesn't set it regardless of -ffast-math or -fno-math-errno. This leads to this case where sqrt(-1.0) will not set errno despite us setting math_errhandling to MATH_ERRNO | MATH_ERREXCEPT: https://godbolt.org/z/ZhMT_z

For now it might be better just to define this conservatively as

#define math_errhandling (MATH_ERREXCEPT)

since it seems a little tough to determine whether math functions will set errno across both gcc and clang, but it is known that they will set the floating point exceptions.

113

It corresponds to the tagp argument for nan:

These functions shall return a quiet NaN, if available, with content indicated through tagp.

This allows the creation of differently "tagged" NaN values (the tags are in the trailing bits). Both musl and glibc use "" as the tag so this looks good.

sivachandra marked an inline comment as done.Mar 25 2020, 10:50 AM
sivachandra added inline comments.
libc/config/linux/api.td
79

There is a lot of information here so let me try to answer in parts.

Before I start, I would like to point out that a libc can itself be compiled with different values of math_errhandling. So, the options -ffast-math and/or -fno-math-errno are only applicable to your translation unit and not to your entire program in case of your godbolt examples.

About -ffast-math and -fno-math-errno: These are compiler options wherein the compilers are saying that irrespective of what the libc does, we will try to make your code run faster. The speed might come at the cost of non-compliance with standards. For example, -ffast-math implies -fno-math-errno and -funsafe-math-optimizations. The documentation for -funsafe-math-optimizations says, "Allow optimizations for floating-point arithmetic that (a) assume that arguments and results are valid and (b) may violate IEEE or ANSI standards." So, under -ffast-math, compilers *might* generate code which does not give any error information. Some instructions generated by the compilers can still set the floating point exceptions. But, in general, user code cannot except that any error information will be available. The way to surface this to the user code is to set math_errhandling to 0 under __FAST_MATH__.

Coming to the differences between clang and gcc you are seeing in your sqrt examples, it is because gcc and clang use different interpretations of the options and has nothing to do with the under lying libc they use if at all. After all, -ffast-math and -fno-math-errno are compiler options, and also best effort options. If you notice, both clang and gcc do not call sqrt at all when -ffast-math is used. Likewise, gcc chooses to call sqrt with or without -fno-math-errno. On the other hand, clang does not call sqrt even when -fno-math-errno is used. The important point is that these differences do not reflect or dictate what the underlying libc does or should do.

libc/include/CMakeLists.txt