svn commit: r230368 - head/tools/regression/usr.bin/cc
Roman Divacky
rdivacky at freebsd.org
Fri Jan 20 08:04:14 UTC 2012
http://llvm.org/bugs/show_bug.cgi?id=11406 says this has been
fixed, is this just problem with us having older clang in base?
On Fri, Jan 20, 2012 at 06:57:22AM +0000, David Schultz wrote:
> Author: das
> Date: Fri Jan 20 06:57:21 2012
> New Revision: 230368
> URL: http://svn.freebsd.org/changeset/base/230368
>
> Log:
> These tests check whether the compiler evaluates floating-point
> expressions properly. Some of the tests depend on the compiler
> implementing C99's FENV_ACCESS pragma, and only commercial compilers
> do; those tests are currently skipped. If any of the enabled tests
> fail, then odds are the libm regression tests will fail also.
> This should make it easier to diagnose reported problems on platforms
> I don't have.
>
> Currently, gcc passes all the tests that don't depend on FENV_ACCESS
> on amd64 and sparc64. Clang fails a few on amd64 (see clang bug
> 11406). Both gcc and clang fare poorly on i386, which has well-known
> issues.
>
> Added:
> head/tools/regression/usr.bin/cc/
> head/tools/regression/usr.bin/cc/Makefile (contents, props changed)
> head/tools/regression/usr.bin/cc/float.c (contents, props changed)
> head/tools/regression/usr.bin/cc/float.t (contents, props changed)
>
> Added: head/tools/regression/usr.bin/cc/Makefile
> ==============================================================================
> --- /dev/null 00:00:00 1970 (empty, because file is newly added)
> +++ head/tools/regression/usr.bin/cc/Makefile Fri Jan 20 06:57:21 2012 (r230368)
> @@ -0,0 +1,12 @@
> +# $FreeBSD$
> +
> +TESTS= float
> +CFLAGS+=-lm
> +
> +.PHONY: tests
> +tests: ${TESTS}
> + for p in ${TESTS}; do ${.OBJDIR}/$$p; done
> +
> +.PHONY: clean
> +clean:
> + -rm -f ${TESTS}
>
> Added: head/tools/regression/usr.bin/cc/float.c
> ==============================================================================
> --- /dev/null 00:00:00 1970 (empty, because file is newly added)
> +++ head/tools/regression/usr.bin/cc/float.c Fri Jan 20 06:57:21 2012 (r230368)
> @@ -0,0 +1,271 @@
> +/*-
> + * Copyright (c) 2012 David Schultz <das at FreeBSD.org>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in the
> + * documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +/*
> + * Test that floating-point arithmetic works as specified by the C standard.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include <fenv.h>
> +#include <float.h>
> +#include <math.h>
> +#include <stdio.h>
> +
> +#ifdef __i386__
> +#include <ieeefp.h>
> +#endif
> +
> +#define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \
> + FE_OVERFLOW | FE_UNDERFLOW)
> +
> +#define TWICE(x) ((x) + (x))
> +#define test(desc, pass) test1((desc), (pass), 0)
> +#define skiptest(desc, pass) test1((desc), (pass), 1)
> +
> +#pragma STDC FENV_ACCESS ON
> +
> +static const float one_f = 1.0 + FLT_EPSILON / 2;
> +static const double one_d = 1.0 + DBL_EPSILON / 2;
> +static const long double one_ld = 1.0L + LDBL_EPSILON / 2;
> +
> +static int testnum, failures;
> +
> +static void
> +test1(const char *testdesc, int pass, int skip)
> +{
> +
> + testnum++;
> + printf("%sok %d - %s%s\n", pass || skip ? "" : "not ", testnum,
> + skip ? "(SKIPPED) " : "", testdesc);
> + if (!pass && !skip)
> + failures++;
> +}
> +
> +/*
> + * Compare d1 and d2 using special rules: NaN == NaN and +0 != -0.
> + */
> +static int
> +fpequal(long double d1, long double d2)
> +{
> +
> + if (d1 != d2)
> + return (isnan(d1) && isnan(d2));
> + return (copysignl(1.0, d1) == copysignl(1.0, d2));
> +}
> +
> +void
> +run_zero_opt_test(double d1, double d2)
> +{
> +
> + test("optimizations don't break the sign of 0",
> + fpequal(d1 - d2, 0.0)
> + && fpequal(-d1 + 0.0, 0.0)
> + && fpequal(-d1 - d2, -0.0)
> + && fpequal(-(d1 - d2), -0.0)
> + && fpequal(-d1 - (-d2), 0.0));
> +}
> +
> +void
> +run_inf_opt_test(double d)
> +{
> +
> + test("optimizations don't break infinities",
> + fpequal(d / d, NAN) && fpequal(0.0 * d, NAN));
> +}
> +
> +static inline double
> +todouble(long double ld)
> +{
> +
> + return (ld);
> +}
> +
> +static inline float
> +tofloat(double d)
> +{
> +
> + return (d);
> +}
> +
> +void
> +run_tests(void)
> +{
> + volatile long double vld;
> + long double ld;
> + volatile double vd;
> + double d;
> + volatile float vf;
> + float f;
> + int x;
> +
> + test("sign bits", fpequal(-0.0, -0.0) && !fpequal(0.0, -0.0));
> +
> + vd = NAN;
> + test("NaN equality", fpequal(NAN, NAN) && NAN != NAN && vd != vd);
> +
> + feclearexcept(ALL_STD_EXCEPT);
> + test("NaN comparison returns false", !(vd <= vd));
> + /*
> + * XXX disabled; gcc/amd64 botches this IEEE 754 requirement by
> + * emitting ucomisd instead of comisd.
> + */
> + skiptest("FENV_ACCESS: NaN comparison raises invalid exception",
> + fetestexcept(ALL_STD_EXCEPT) == FE_INVALID);
> +
> + vd = 0.0;
> + run_zero_opt_test(vd, vd);
> +
> + vd = INFINITY;
> + run_inf_opt_test(vd);
> +
> + feclearexcept(ALL_STD_EXCEPT);
> + vd = INFINITY;
> + x = (int)vd;
> + /* XXX disabled (works with -O0); gcc doesn't support FENV_ACCESS */
> + skiptest("FENV_ACCESS: Inf->int conversion raises invalid exception",
> + fetestexcept(ALL_STD_EXCEPT) == FE_INVALID);
> +
> + /* Raising an inexact exception here is an IEEE-854 requirement. */
> + feclearexcept(ALL_STD_EXCEPT);
> + vd = 0.75;
> + x = (int)vd;
> + test("0.75->int conversion rounds toward 0, raises inexact exception",
> + x == 0 && fetestexcept(ALL_STD_EXCEPT) == FE_INEXACT);
> +
> + feclearexcept(ALL_STD_EXCEPT);
> + vd = -42.0;
> + x = (int)vd;
> + test("-42.0->int conversion is exact, raises no exception",
> + x == -42 && fetestexcept(ALL_STD_EXCEPT) == 0);
> +
> + feclearexcept(ALL_STD_EXCEPT);
> + x = (int)INFINITY;
> + /* XXX disabled; gcc doesn't support FENV_ACCESS */
> + skiptest("FENV_ACCESS: const Inf->int conversion raises invalid",
> + fetestexcept(ALL_STD_EXCEPT) == FE_INVALID);
> +
> + feclearexcept(ALL_STD_EXCEPT);
> + x = (int)0.5;
> + /* XXX disabled; gcc doesn't support FENV_ACCESS */
> + skiptest("FENV_ACCESS: const double->int conversion raises inexact",
> + x == 0 && fetestexcept(ALL_STD_EXCEPT) == FE_INEXACT);
> +
> + test("compile-time constants don't have too much precision",
> + one_f == 1.0L && one_d == 1.0L && one_ld == 1.0L);
> +
> + test("const minimum rounding precision",
> + 1.0F + FLT_EPSILON != 1.0F &&
> + 1.0 + DBL_EPSILON != 1.0 &&
> + 1.0L + LDBL_EPSILON != 1.0L);
> +
> + /* It isn't the compiler's fault if this fails on FreeBSD/i386. */
> + vf = FLT_EPSILON;
> + vd = DBL_EPSILON;
> + vld = LDBL_EPSILON;
> + test("runtime minimum rounding precision",
> + 1.0F + vf != 1.0F && 1.0 + vd != 1.0 && 1.0L + vld != 1.0L);
> +
> + test("explicit float to float conversion discards extra precision",
> + (float)(1.0F + FLT_EPSILON * 0.5F) == 1.0F &&
> + (float)(1.0F + vf * 0.5F) == 1.0F);
> + test("explicit double to float conversion discards extra precision",
> + (float)(1.0 + FLT_EPSILON * 0.5) == 1.0F &&
> + (float)(1.0 + vf * 0.5) == 1.0F);
> + test("explicit ldouble to float conversion discards extra precision",
> + (float)(1.0L + FLT_EPSILON * 0.5L) == 1.0F &&
> + (float)(1.0L + vf * 0.5L) == 1.0F);
> +
> + test("explicit double to double conversion discards extra precision",
> + (double)(1.0 + DBL_EPSILON * 0.5) == 1.0 &&
> + (double)(1.0 + vd * 0.5) == 1.0);
> + test("explicit ldouble to double conversion discards extra precision",
> + (double)(1.0L + DBL_EPSILON * 0.5L) == 1.0 &&
> + (double)(1.0L + vd * 0.5L) == 1.0);
> +
> + /*
> + * FLT_EVAL_METHOD > 1 implies that float expressions are always
> + * evaluated in double precision or higher, but some compilers get
> + * this wrong when registers spill to memory. The following expression
> + * forces a spill when there are at most 8 FP registers.
> + */
> + test("implicit promption to double or higher precision is consistent",
> +#if FLT_EVAL_METHOD == 1 || FLT_EVAL_METHOD == 2 || defined(__i386__)
> + TWICE(TWICE(TWICE(TWICE(TWICE(
> + TWICE(TWICE(TWICE(TWICE(1.0F + vf * 0.5F)))))))))
> + == (1.0 + FLT_EPSILON * 0.5) * 512.0
> +#else
> + 1
> +#endif
> + );
> +
> + f = 1.0 + FLT_EPSILON * 0.5;
> + d = 1.0L + DBL_EPSILON * 0.5L;
> + test("const assignment discards extra precision", f == 1.0F && d == 1.0);
> +
> + f = 1.0 + vf * 0.5;
> + d = 1.0L + vd * 0.5L;
> + test("variable assignment discards explicit extra precision",
> + f == 1.0F && d == 1.0);
> + f = 1.0F + vf * 0.5F;
> + d = 1.0 + vd * 0.5;
> + test("variable assignment discards implicit extra precision",
> + f == 1.0F && d == 1.0);
> +
> + test("return discards extra precision",
> + tofloat(1.0 + vf * 0.5) == 1.0F &&
> + todouble(1.0L + vd * 0.5L) == 1.0);
> +
> + fesetround(FE_UPWARD);
> + /* XXX disabled (works with -frounding-math) */
> + skiptest("FENV_ACCESS: constant arithmetic respects rounding mode",
> + 1.0F + FLT_MIN == 1.0F + FLT_EPSILON &&
> + 1.0 + DBL_MIN == 1.0 + DBL_EPSILON &&
> + 1.0L + LDBL_MIN == 1.0L + LDBL_EPSILON);
> + fesetround(FE_TONEAREST);
> +
> + ld = vld * 0.5;
> + test("associativity is respected",
> + 1.0L + ld + (LDBL_EPSILON * 0.5) == 1.0L &&
> + 1.0L + (LDBL_EPSILON * 0.5) + ld == 1.0L &&
> + ld + 1.0 + (LDBL_EPSILON * 0.5) == 1.0L &&
> + ld + (LDBL_EPSILON * 0.5) + 1.0 == 1.0L + LDBL_EPSILON);
> +}
> +
> +int
> +main(int argc, char *argv[])
> +{
> +
> + printf("1..26\n");
> +
> +#ifdef __i386__
> + fpsetprec(FP_PE);
> +#endif
> + run_tests();
> +
> + return (failures);
> +}
>
> Added: head/tools/regression/usr.bin/cc/float.t
> ==============================================================================
> --- /dev/null 00:00:00 1970 (empty, because file is newly added)
> +++ head/tools/regression/usr.bin/cc/float.t Fri Jan 20 06:57:21 2012 (r230368)
> @@ -0,0 +1,10 @@
> +#!/bin/sh
> +# $FreeBSD$
> +
> +cd `dirname $0`
> +
> +executable=`basename $0 .t`
> +
> +make $executable 2>&1 > /dev/null
> +
> +exec ./$executable
More information about the svn-src-all
mailing list