diff --git a/compiler-rt/lib/adddf3.c b/compiler-rt/lib/adddf3.c index c41cc2ecd498..1ec43dcf58e2 100644 --- a/compiler-rt/lib/adddf3.c +++ b/compiler-rt/lib/adddf3.c @@ -1,16 +1,20 @@ -/* - * The LLVM Compiler Infrastructure - * - * This file is distributed under the University of Illinois Open Source - * License. See LICENSE.TXT for details. - */ +//===-- lib/adddf3.c - Double-precision addition and subtraction --*- C -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements double-precision soft-float addition and subtraction +// with the IEEE-754 default rounding (to nearest, ties to even). +// +//===----------------------------------------------------------------------===// #define DOUBLE_PRECISION #include "fp_lib.h" -// This file implements double-precision soft-float addition and subtraction -// with the IEEE-754 default rounding (to nearest, ties to even). - fp_t __adddf3(fp_t a, fp_t b) { rep_t aRep = toRep(a); diff --git a/compiler-rt/lib/addsf3.c b/compiler-rt/lib/addsf3.c index e6d13208429f..fec14e838518 100644 --- a/compiler-rt/lib/addsf3.c +++ b/compiler-rt/lib/addsf3.c @@ -1,16 +1,20 @@ -/* - * The LLVM Compiler Infrastructure - * - * This file is distributed under the University of Illinois Open Source - * License. See LICENSE.TXT for details. - */ +//===-- lib/addsf3.c - Single-precision addition and subtraction --*- C -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements single-precision soft-float addition and subtraction +// with the IEEE-754 default rounding (to nearest, ties to even). +// +//===----------------------------------------------------------------------===// #define SINGLE_PRECISION #include "fp_lib.h" -// This file implements single-precision soft-float addition and subtraction -// with the IEEE-754 default rounding (to nearest, ties to even). - fp_t __addsf3(fp_t a, fp_t b) { rep_t aRep = toRep(a); diff --git a/compiler-rt/lib/comparedf2.c b/compiler-rt/lib/comparedf2.c index de700808a925..5c5ee9d65bf2 100644 --- a/compiler-rt/lib/comparedf2.c +++ b/compiler-rt/lib/comparedf2.c @@ -1,16 +1,15 @@ -/* - * The LLVM Compiler Infrastructure - * - * This file is distributed under the University of Illinois Open Source - * License. See LICENSE.TXT for details. - */ - -#define DOUBLE_PRECISION -#include "fp_lib.h" - -// This file implements the following soft-float comparison routines: +//===-- lib/comparedf2.c - Double-precision comparisons -----------*- C -*-===// // -// __eqdf2 __gedf2 __nedf2 +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// // This file implements the following soft-float comparison routines: +// +// __eqdf2 __gedf2 __unorddf2 // __ledf2 __gtdf2 // __ltdf2 // __nedf2 @@ -35,6 +34,11 @@ // // Note that __ledf2( ) and __gedf2( ) are identical except in their handling of // NaN values. +// +//===----------------------------------------------------------------------===// + +#define DOUBLE_PRECISION +#include "fp_lib.h" enum LE_RESULT { LE_LESS = -1, @@ -75,7 +79,6 @@ enum LE_RESULT __ledf2(fp_t a, fp_t b) { } } - enum GE_RESULT { GE_LESS = -1, GE_EQUAL = 0, @@ -109,6 +112,8 @@ int __unorddf2(fp_t a, fp_t b) { return aAbs > infRep || bAbs > infRep; } +// The following are alternative names for the preceeding routines. + enum LE_RESULT __eqdf2(fp_t a, fp_t b) { return __ledf2(a, b); } diff --git a/compiler-rt/lib/comparesf2.c b/compiler-rt/lib/comparesf2.c index 6706f192a943..fd0572401117 100644 --- a/compiler-rt/lib/comparesf2.c +++ b/compiler-rt/lib/comparesf2.c @@ -9,7 +9,7 @@ // // This file implements the following soft-fp_t comparison routines: // -// __eqsf2 __gesf2 __nesf2 +// __eqsf2 __gesf2 __unordsf2 // __lesf2 __gtsf2 // __ltsf2 // __nesf2 @@ -79,7 +79,6 @@ enum LE_RESULT __lesf2(fp_t a, fp_t b) { } } - enum GE_RESULT { GE_LESS = -1, GE_EQUAL = 0, @@ -113,7 +112,7 @@ int __unordsf2(fp_t a, fp_t b) { return aAbs > infRep || bAbs > infRep; } -// The following are just other names for the forgoing routines. +// The following are alternative names for the preceeding routines. enum LE_RESULT __eqsf2(fp_t a, fp_t b) { return __lesf2(a, b); @@ -130,4 +129,3 @@ enum LE_RESULT __nesf2(fp_t a, fp_t b) { enum GE_RESULT __gtsf2(fp_t a, fp_t b) { return __gesf2(a, b); } - diff --git a/compiler-rt/lib/extendsfdf2.c b/compiler-rt/lib/extendsfdf2.c index 87819bd7a5b6..025eb9572446 100644 --- a/compiler-rt/lib/extendsfdf2.c +++ b/compiler-rt/lib/extendsfdf2.c @@ -1,18 +1,15 @@ -/* - * The LLVM Compiler Infrastructure - * - * This file is distributed under the University of Illinois Open Source - * License. See LICENSE.TXT for details. - */ - -#include -#include - +//===-- lib/extendsfdf2.c - single -> double conversion -----------*- C -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// // This file implements a fairly generic conversion from a narrower to a wider -// IEEE-754 floating-point type. The next 10 lines parametrize which types -// are to be used as the source and destination, the actual name used for -// the conversion, and a suitable CLZ function for the source representation -// type. +// IEEE-754 floating-point type. The constants and types defined following the +// includes below parameterize the conversion. // // This routine can be trivially adapted to support conversions from // half-precision or to quad-precision. It does not support types that don't @@ -38,8 +35,11 @@ // // 2. quiet NaNs, if supported, are indicated by the leading bit of the // significand field being set +// +//===----------------------------------------------------------------------===// -#define widen __extendsfdf2 +#include +#include typedef float src_t; typedef uint32_t src_rep_t; @@ -67,7 +67,7 @@ static inline dst_t dstFromRep(dst_rep_t x) { // End helper routines. Conversion implementation follows. -dst_t widen(src_t a) { +dst_t __extendsfdf2(src_t a) { // Various constants whose values follow from the type parameters. // Any reasonable optimizer will fold and propagate all of these. @@ -75,22 +75,25 @@ dst_t widen(src_t a) { const int srcExpBits = srcBits - srcSigBits - 1; const int srcInfExp = (1 << srcExpBits) - 1; const int srcExpBias = srcInfExp >> 1; + const src_rep_t srcMinNormal = SRC_REP_C(1) << srcSigBits; const src_rep_t srcInfinity = (src_rep_t)srcInfExp << srcSigBits; const src_rep_t srcSignMask = SRC_REP_C(1) << (srcSigBits + srcExpBits); const src_rep_t srcAbsMask = srcSignMask - 1; const src_rep_t srcQNaN = SRC_REP_C(1) << (srcSigBits - 1); const src_rep_t srcNaNCode = srcQNaN - 1; + const int dstBits = sizeof(dst_t)*CHAR_BIT; const int dstExpBits = dstBits - dstSigBits - 1; const int dstInfExp = (1 << dstExpBits) - 1; const int dstExpBias = dstInfExp >> 1; + const dst_rep_t dstMinNormal = DST_REP_C(1) << dstSigBits; // Break a into a sign and representation of the absolute value - src_rep_t aRep = srcToRep(a); - src_rep_t aAbs = aRep & srcAbsMask; - src_rep_t sign = aRep & srcSignMask; + const src_rep_t aRep = srcToRep(a); + const src_rep_t aAbs = aRep & srcAbsMask; + const src_rep_t sign = aRep & srcSignMask; dst_rep_t absResult; if (aAbs - srcMinNormal < srcInfinity - srcMinNormal) { @@ -104,11 +107,11 @@ dst_t widen(src_t a) { else if (aAbs >= srcInfinity) { // a is NaN or infinity. // Conjure the result by beginning with infinity, then setting the qNaN - // bit if appropriate and then by right-aligning the rest of the - // trailing NaN payload field. + // bit (if needed) and right-aligning the rest of the trailing NaN + // payload field. absResult = (dst_rep_t)dstInfExp << dstSigBits; absResult |= (dst_rep_t)(aAbs & srcQNaN) << (dstSigBits - srcSigBits); - absResult |= (aAbs & srcNaNCode); + absResult |= aAbs & srcNaNCode; } else if (aAbs) { @@ -128,6 +131,6 @@ dst_t widen(src_t a) { } // Apply the signbit to (dst_t)abs(a). - dst_rep_t result = absResult | (dst_rep_t)sign << (dstBits - srcBits); + const dst_rep_t result = absResult | (dst_rep_t)sign << (dstBits - srcBits); return dstFromRep(result); } diff --git a/compiler-rt/lib/fp_lib.h b/compiler-rt/lib/fp_lib.h index b3c01049119d..c8c72342dc6f 100644 --- a/compiler-rt/lib/fp_lib.h +++ b/compiler-rt/lib/fp_lib.h @@ -1,8 +1,22 @@ +//===-- lib/fp_lib.h - Floating-point utilities -------------------*- C -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// // This file is a configuration header for soft-float routines in compiler-rt. -// This file does not provide any part of the compiler-rt interface. - +// This file does not provide any part of the compiler-rt interface, but defines +// many useful constants and utility routines that are used in the +// implementation of the soft-float routines in compiler-rt. +// // Assumes that float and double correspond to the IEEE-754 binary32 and -// binary64 types, respectively. +// binary64 types, respectively, and that integer endianness matches floating +// point endianness on the target platform. +// +//===----------------------------------------------------------------------===// #ifndef FP_LIB_HEADER #define FP_LIB_HEADER @@ -12,9 +26,6 @@ #include #if defined SINGLE_PRECISION -#if 0 -#pragma mark single definitions -#endif typedef uint32_t rep_t; typedef int32_t srep_t; @@ -27,9 +38,6 @@ static inline int rep_clz(rep_t a) { } #elif defined DOUBLE_PRECISION -#if 0 -#pragma mark double definitions -#endif typedef uint64_t rep_t; typedef int64_t srep_t; @@ -52,21 +60,11 @@ static inline int rep_clz(rep_t a) { #error Either SINGLE_PRECISION or DOUBLE_PRECISION must be defined. #endif -#if 0 -#pragma mark - -#pragma mark integer constants -#endif - #define typeWidth (sizeof(rep_t)*CHAR_BIT) #define exponentBits (typeWidth - significandBits - 1) #define maxExponent ((1 << exponentBits) - 1) #define exponentBias (maxExponent >> 1) -#if 0 -#pragma mark - -#pragma mark rep_t constants -#endif - #define implicitBit (REP_C(1) << significandBits) #define significandMask (implicitBit - 1U) #define signBit (REP_C(1) << (significandBits + exponentBits)) @@ -77,11 +75,6 @@ static inline int rep_clz(rep_t a) { #define quietBit (implicitBit >> 1) #define qnanRep (exponentMask | quietBit) -#if 0 -#pragma mark - -#pragma mark generic functions -#endif - static inline rep_t toRep(fp_t x) { const union { fp_t f; rep_t i; } rep = {.f = x}; return rep.i; diff --git a/compiler-rt/lib/muldf3.c b/compiler-rt/lib/muldf3.c index 77e9ed19c455..2ea197ff94f9 100644 --- a/compiler-rt/lib/muldf3.c +++ b/compiler-rt/lib/muldf3.c @@ -1,21 +1,25 @@ -/* - * The LLVM Compiler Infrastructure - * - * This file is distributed under the University of Illinois Open Source - * License. See LICENSE.TXT for details. - */ +//===-- lib/muldf3.c - Double-precision multiplication ------------*- C -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements double-precision soft-float multiplication +// with the IEEE-754 default rounding (to nearest, ties to even). +// +//===----------------------------------------------------------------------===// #define DOUBLE_PRECISION #include "fp_lib.h" -// This file implements double-precision soft-float multiplication with the -// IEEE-754 default rounding (to nearest, ties to even). - #define loWord(a) (a & 0xffffffffU) #define hiWord(a) (a >> 32) // 64x64 -> 128 wide multiply for platforms that don't have such an operation; -// some 64-bit platforms have this operation, but they tend to have hardware +// many 64-bit platforms have this operation, but they tend to have hardware // floating-point, so we don't bother with a special case for them here. static inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) { // Each of the component 32x32 -> 64 products @@ -23,7 +27,7 @@ static inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) { const uint64_t plohi = loWord(a) * hiWord(b); const uint64_t philo = hiWord(a) * loWord(b); const uint64_t phihi = hiWord(a) * hiWord(b); - // Sum terms that compute to lo in a way that allows us to get the carry + // Sum terms that contribute to lo in a way that allows us to get the carry const uint64_t r0 = loWord(plolo); const uint64_t r1 = hiWord(plolo) + loWord(plohi) + loWord(philo); *lo = r0 + (r1 << 32); diff --git a/compiler-rt/lib/mulsf3.c b/compiler-rt/lib/mulsf3.c index 8c8b3144f5d8..56a1ee36ab2b 100644 --- a/compiler-rt/lib/mulsf3.c +++ b/compiler-rt/lib/mulsf3.c @@ -1,16 +1,20 @@ -/* - * The LLVM Compiler Infrastructure - * - * This file is distributed under the University of Illinois Open Source - * License. See LICENSE.TXT for details. - */ +//===-- lib/mulsf3.c - Single-precision multiplication ------------*- C -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements single-precision soft-float multiplication +// with the IEEE-754 default rounding (to nearest, ties to even). +// +//===----------------------------------------------------------------------===// #define SINGLE_PRECISION #include "fp_lib.h" -// This file implements single-precision soft-float multiplication with the -// IEEE-754 default rounding (to nearest, ties to even). - // 32x32 --> 64 bit multiply static inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) { const uint64_t product = (uint64_t)a*b; diff --git a/compiler-rt/lib/negdf2.c b/compiler-rt/lib/negdf2.c index edc2a6c82f28..eb6efc722d4e 100644 --- a/compiler-rt/lib/negdf2.c +++ b/compiler-rt/lib/negdf2.c @@ -1,13 +1,19 @@ -/* - * The LLVM Compiler Infrastructure - * - * This file is distributed under the University of Illinois Open Source - * License. See LICENSE.TXT for details. - */ +//===-- lib/negdf3.c - double-precision negation ------------------*- C -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements double-precision soft-float negation. +// +//===----------------------------------------------------------------------===// #define DOUBLE_PRECISION #include "fp_lib.h" -fp_t __negsf2(fp_t a) { +fp_t __negdf2(fp_t a) { return fromRep(toRep(a) ^ signBit); } diff --git a/compiler-rt/lib/negsf2.c b/compiler-rt/lib/negsf2.c index f96d19ccdb57..f21c7605349f 100644 --- a/compiler-rt/lib/negsf2.c +++ b/compiler-rt/lib/negsf2.c @@ -1,9 +1,15 @@ -/* - * The LLVM Compiler Infrastructure - * - * This file is distributed under the University of Illinois Open Source - * License. See LICENSE.TXT for details. - */ +//===-- lib/negsf3.c - single-precision negation ------------------*- C -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements single-precision soft-float negation. +// +//===----------------------------------------------------------------------===// #define SINGLE_PRECISION #include "fp_lib.h" diff --git a/compiler-rt/lib/truncdfsf2.c b/compiler-rt/lib/truncdfsf2.c new file mode 100644 index 000000000000..6313c87af28d --- /dev/null +++ b/compiler-rt/lib/truncdfsf2.c @@ -0,0 +1,169 @@ +//===-- lib/truncdfsf2.c - double -> single conversion ------------*- C -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a fairly generic conversion from a wider to a narrower +// IEEE-754 floating-point type in the default (round to nearest, ties to even) +// rounding mode. The constants and types defined following the includes below +// parameterize the conversion. +// +// This routine can be trivially adapted to support conversions to +// half-precision or from quad-precision. It does not support types that don't +// use the usual IEEE-754 interchange formats; specifically, some work would be +// needed to adapt it to (for example) the Intel 80-bit format or PowerPC +// double-double format. +// +// Note please, however, that this implementation is only intended to support +// *narrowing* operations; if you need to convert to a *wider* floating-point +// type (e.g. float -> double), then this routine will not do what you want it +// to. +// +// It also requires that integer types at least as large as both formats +// are available on the target platform; this may pose a problem when trying +// to add support for quad on some 32-bit systems, for example. +// +// Finally, the following assumptions are made: +// +// 1. floating-point types and integer types have the same endianness on the +// target platform +// +// 2. quiet NaNs, if supported, are indicated by the leading bit of the +// significand field being set +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + +typedef double src_t; +typedef uint64_t src_rep_t; +#define SRC_REP_C UINT64_C +static const int srcSigBits = 52; + +typedef float dst_t; +typedef uint32_t dst_rep_t; +#define DST_REP_C UINT32_C +static const int dstSigBits = 23; + +// End of specialization parameters. Two helper routines for conversion to and +// from the representation of floating-point data as integer values follow. + +static inline src_rep_t srcToRep(src_t x) { + const union { src_t f; src_rep_t i; } rep = {.f = x}; + return rep.i; +} + +static inline dst_t dstFromRep(dst_rep_t x) { + const union { dst_t f; dst_rep_t i; } rep = {.i = x}; + return rep.f; +} + +// End helper routines. Conversion implementation follows. + +dst_t __truncdfsf2(src_t a) { + + // Various constants whose values follow from the type parameters. + // Any reasonable optimizer will fold and propagate all of these. + const int srcBits = sizeof(src_t)*CHAR_BIT; + const int srcExpBits = srcBits - srcSigBits - 1; + const int srcInfExp = (1 << srcExpBits) - 1; + const int srcExpBias = srcInfExp >> 1; + + const src_rep_t srcMinNormal = SRC_REP_C(1) << srcSigBits; + const src_rep_t srcSignificandMask = srcMinNormal - 1; + const src_rep_t srcInfinity = (src_rep_t)srcInfExp << srcSigBits; + const src_rep_t srcSignMask = SRC_REP_C(1) << (srcSigBits + srcExpBits); + const src_rep_t srcAbsMask = srcSignMask - 1; + const src_rep_t srcQNaN = SRC_REP_C(1) << (srcSigBits - 1); + const src_rep_t srcNaNCode = srcQNaN - 1; + const src_rep_t roundMask = (SRC_REP_C(1) << (srcSigBits - dstSigBits)) - 1; + const src_rep_t halfway = SRC_REP_C(1) << (srcSigBits - dstSigBits - 1); + + const int dstBits = sizeof(dst_t)*CHAR_BIT; + const int dstExpBits = dstBits - dstSigBits - 1; + const int dstInfExp = (1 << dstExpBits) - 1; + const int dstExpBias = dstInfExp >> 1; + + const int underflowExponent = srcExpBias + 1 - dstExpBias; + const int overflowExponent = srcExpBias + dstInfExp - dstExpBias; + const src_rep_t underflow = (src_rep_t)underflowExponent << srcSigBits; + const src_rep_t overflow = (src_rep_t)overflowExponent << srcSigBits; + + const dst_rep_t dstQNaN = DST_REP_C(1) << (dstSigBits - 1); + const dst_rep_t dstNaNCode = dstQNaN - 1; + + // Break a into a sign and representation of the absolute value + const src_rep_t aRep = srcToRep(a); + const src_rep_t aAbs = aRep & srcAbsMask; + const src_rep_t sign = aRep & srcSignMask; + dst_rep_t absResult; + + if (aAbs - underflow < aAbs - overflow) { + // The exponent of a is within the range of normal numbers in the + // destination format. We can convert by simply right-shifting with + // rounding and adjusting the exponent. + absResult = aAbs >> (srcSigBits - dstSigBits); + absResult -= (dst_rep_t)(srcExpBias - dstExpBias) << dstSigBits; + + const src_rep_t roundBits = aAbs & roundMask; + + // Round to nearest + if (roundBits > halfway) + absResult++; + + // Ties to even + else if (roundBits == halfway) + absResult += absResult & 1; + } + + else if (aAbs > srcInfinity) { + // a is NaN. + // Conjure the result by beginning with infinity, setting the qNaN + // bit and inserting the (truncated) trailing NaN field. + absResult = (dst_rep_t)dstInfExp << dstSigBits; + absResult |= dstQNaN; + absResult |= aAbs & dstNaNCode; + } + + else if (aAbs > overflow) { + // a overflows to infinity. + absResult = (dst_rep_t)dstInfExp << dstSigBits; + } + + else { + // a underflows on conversion to the destination type or is an exact + // zero. The result may be a denormal or zero. Extract the exponent + // to get the shift amount for the denormalization. + const int aExp = aAbs >> srcSigBits; + const int shift = srcExpBias - dstExpBias - aExp + 1; + + const src_rep_t significand = aRep & srcSignificandMask | srcMinNormal; + + // Right shift by the denormalization amount with sticky. + if (shift > srcSigBits) { + absResult = 0; + } else { + const bool sticky = significand << (srcBits - shift); + src_rep_t denormalizedSignificand = significand >> shift | sticky; + absResult = denormalizedSignificand >> (srcSigBits - dstSigBits); + const src_rep_t roundBits = denormalizedSignificand & roundMask; + // Round to nearest + if (roundBits > halfway) + absResult++; + // Ties to even + else if (roundBits == halfway) + absResult += absResult & 1; + } + } + + // Apply the signbit to (dst_t)abs(a). + const dst_rep_t result = absResult | sign >> (srcBits - dstBits); + return dstFromRep(result); + +}