On Thu, 1 Mar 2018, Tejas Joshi wrote: > "GCC supports built-in functions for math.h and complex.h functions in > the C99/C11 standards (both folding calls for constant arguments, and > expanding inline when the processor supports appropriate > functionality). More such functions have been added in ISO/IEC TS > 18661, supporting features of IEEE 754-2008. It would be useful to > have built-in functions for those, both folding for constant > arguments, and expanding inline where appropriate (e.g. for roundeven > and the functions rounding result to narrower type, on some > processors; roundeven can be inlined on x86 for SSE4.1 and later, and > the narrowing functions on IA64 and POWER8, for example)". > > The above Project Idea is made available on 'Summer of Code' wiki of > GNU GCC Website. I wanted to have some more details about above idea > regarding to what is expected for implementation and expected output > for the same.
See <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1778.pdf> for a near-final draft of TS 18661-1 that says what various of the functions mentioned should do. In most cases you'd be folding for constant arguments and generating appropriate instructions for non-constant arguments if the target processor has such instructions - for non-constant arguments where the processor doesn't have relevant instructions, the implementation would be left to libm (e.g. glibc 2.25 has most of these functions) as it would be too big to expand inline in that case. Here are some examples: * roundeven is similar to existing functions round / ceil / floor / trunc. So you'd define built-in functions (roundeven / roundevenf / roundevenl and _FloatN and _FloatNx variants) similar to those for the older rounding functions, in builtins.def. You'd look at all the places through the compiler that are needed to handle those functions - where the existing ones get folded for constant arguments, where they end up getting converted to appropriate RTL using corresponding .md patterns for processors supporting expanding them inline for non-constant arguments, and update all those places to handle these functions. Documentation of built-in functions (extend.texi) and instruction patterns (md.texi) would need updating. Testcases would need adding to verify appropriate folding for constant arguments. You'd also implement the new instruction patterns for at least one target - for example, for x86 (roundss and roundsd SSE4.1 instructions, immediate operand 8). There would then be architecture-specific tests needed for the testsuite to verify the appropriate code generation (both scanning assembler output and execution tests). Some other architectures also have appropriate instructions, but once things have been illustrated by doing it for one architecture, the target maintainers for other architectures might well do those updates. Doing roundeven would be a good starting point for becoming familiar with the relevant parts of the compiler, because there are existing built-in functions that are very similar and so serve as a guide to what you need to change. There are lots of other functions for which built-in functions are also useful, some of which bring their own complications - this project is open-ended, and the number of functions implemented can depend on how long it takes to do each one. * The narrowing functions, e.g. fadd, faddl, daddl, are a bit different from most other built-in math.h functions because the return type is different from the argument types. You could start by adding them to builtins.def similarly to roundeven (with new macros to handle adding such functions for relevant pairs of _FloatN, _FloatNx types). These functions could be folded for constant arguments only if the result is exact, or if -fno-rounding-math -fno-trapping-math (and -fno-math-errno if the result involves overflow / underflow). Probably more interesting than folding them for constant arguments is expanding them inline for non-constant arguments (provided -fno-math-errno). Given -fno-math-errno, those functions can always be expanded inline if the argument and result types have the same floating-point format - for example, f32xaddf64 on all GCC configurations that support _Float32x and _Float64. So you want that to expand to a normal ADD operation (on GIMPLE and then RTL) just as if the user had written normal floating-point addition. But when the functions are genuinely narrowing - fadd taking double arguments and returning float, for example - you can only expand inline for non-constant arguments when the target architecture has appropriate support. There are various existing standard instruction patterns with arguments and results of different modes - for example, mulsidi3, a widening multiplication of SImode (32-bit) operands producing a DImode (64-bit) result. So you might add support for e.g. adddfsf3, a narrowing addition of DFmode operands producing an SFmode result. Then that pattern would need implementing for some suitable target, say POWER8 (rs6000 port), where the instructions for float arithmetic work with double arguments and have the required narrowing semantics. * The fromfp / fromfpx / ufromfp / ufromfpx functions (round to integers of a specified number of bits, in a specified rounding mode, with specified handling of inexact results) are a case with some other complications. Typically I'd expect them to be expanded inline only (for constant arguments or) for constant values of the number of bits and rounding mode, if the target machine has an appropriate instruction. A target hook would need adding for a target to specify the FP_INT_* values used in libm, since that's an ABI that's defined by libm, not by GCC. Then you'd need instruction patterns that might only be supported in certain cases. For example, AArch64 has FCVT instructions to convert floating-point values to 32-bit or 64-bit integers, signed and unsigned, with a rounding mode specified in the instruction. Those instructions set "inexact" for non-integer arguments, so are appropriate for fromfpx / ufromfpx, but for the functions that don't set "inexact" (fromfp / ufromfp) you might use an appropriate FRINT instruction to round to integer in the floating-point type, without setting "inexact", followed by an FCVT instruction to convert that to an integer type. * Classification and comparison macros also naturally have corresponding type-generic built-in functions which are a bit different from the examples discussed above. For example, there ought to be __builtin_iseqsig, see <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77928> for details. __builtin_issignaling, which would need to work by examining the bits of the representation of the argument passed (except on architectures with RISC-V that have instructions that help), would also be useful. (Some such functions, see e.g. bug 77925, were implemented by Tamar Christina but that patch had to be reverted because it caused problems which haven't yet been resolved. However, I don't think anyone has implemented __builtin_iseqsig or __builtin_issignaling for GCC.) -- Joseph S. Myers jos...@codesourcery.com