Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 20 Jan 2012 08:55:51 +0100
From:      Roman Divacky <rdivacky@freebsd.org>
To:        David Schultz <das@FreeBSD.org>
Cc:        svn-src-head@freebsd.org, svn-src-all@freebsd.org, src-committers@freebsd.org
Subject:   Re: svn commit: r230368 - head/tools/regression/usr.bin/cc
Message-ID:  <20120120075551.GA28975@freebsd.org>
In-Reply-To: <201201200657.q0K6vMhf028463@svn.freebsd.org>
References:  <201201200657.q0K6vMhf028463@svn.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
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@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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120120075551.GA28975>