Blame benchtests/bench-math-inlines.c

Packit Service 82fcde
/* Measure math inline functions.
Packit Service 82fcde
   Copyright (C) 2015-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#define SIZE 1024
Packit Service 82fcde
#define TEST_MAIN
Packit Service 82fcde
#define TEST_NAME "math-inlines"
Packit Service 82fcde
#define TEST_FUNCTION test_main ()
Packit Service 82fcde
#include "bench-timing.h"
Packit Service 82fcde
#include "json-lib.h"
Packit Service 82fcde
#include "bench-util.h"
Packit Service 82fcde
Packit Service 82fcde
#include <stdlib.h>
Packit Service 82fcde
#include <math.h>
Packit Service 82fcde
#include <stdint.h>
Packit Service 82fcde
Packit Service 82fcde
#define BOOLTEST(func)					  \
Packit Service 82fcde
static int __attribute__((noinline))			  \
Packit Service 82fcde
func ## _f (double d, int i)				  \
Packit Service 82fcde
{							  \
Packit Service 82fcde
  if (func (d))						  \
Packit Service 82fcde
    return (int) d + i;					  \
Packit Service 82fcde
  else							  \
Packit Service 82fcde
    return 5;						  \
Packit Service 82fcde
}							  \
Packit Service 82fcde
static int						  \
Packit Service 82fcde
func ## _t (volatile double *p, size_t n, size_t iters)   \
Packit Service 82fcde
{							  \
Packit Service 82fcde
  int i, j;						  \
Packit Service 82fcde
  int res = 0;						  \
Packit Service 82fcde
  for (j = 0; j < iters; j++)				  \
Packit Service 82fcde
    for (i = 0; i < n; i++)				  \
Packit Service 82fcde
      if (func ## _f (p[i] * 2.0, i) != 0)		  \
Packit Service 82fcde
	res += 5;					  \
Packit Service 82fcde
  return res;						  \
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#define VALUETEST(func)					  \
Packit Service 82fcde
static int __attribute__((noinline))			  \
Packit Service 82fcde
func ## _f (double d)					  \
Packit Service 82fcde
{							  \
Packit Service 82fcde
  return func (d);					  \
Packit Service 82fcde
}							  \
Packit Service 82fcde
static int						  \
Packit Service 82fcde
func ## _t (volatile double *p, size_t n, size_t iters)	  \
Packit Service 82fcde
{							  \
Packit Service 82fcde
  int i, j;						  \
Packit Service 82fcde
  int res = 0;						  \
Packit Service 82fcde
  for (j = 0; j < iters; j++)				  \
Packit Service 82fcde
    for (i = 0; i < n; i++)				  \
Packit Service 82fcde
      res += func ## _f (p[i] * 2.0);			  \
Packit Service 82fcde
  return res;						  \
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
typedef union
Packit Service 82fcde
{
Packit Service 82fcde
  double value;
Packit Service 82fcde
  uint64_t word;
Packit Service 82fcde
} ieee_double_shape_type;
Packit Service 82fcde
Packit Service 82fcde
#define EXTRACT_WORDS64(i,d)				  \
Packit Service 82fcde
do {							  \
Packit Service 82fcde
  ieee_double_shape_type gh_u;				  \
Packit Service 82fcde
  gh_u.value = (d);					  \
Packit Service 82fcde
  (i) = gh_u.word;					  \
Packit Service 82fcde
} while (0)
Packit Service 82fcde
Packit Service 82fcde
/* Inlines similar to existing math_private.h versions.  */
Packit Service 82fcde
Packit Service 82fcde
static __always_inline int
Packit Service 82fcde
__isnan_inl (double d)
Packit Service 82fcde
{
Packit Service 82fcde
  uint64_t di;
Packit Service 82fcde
  EXTRACT_WORDS64 (di, d);
Packit Service 82fcde
  return (di & 0x7fffffffffffffffull) > 0x7ff0000000000000ull;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static __always_inline int
Packit Service 82fcde
__isinf_ns2 (double d)
Packit Service 82fcde
{
Packit Service 82fcde
  uint64_t di;
Packit Service 82fcde
  EXTRACT_WORDS64 (di, d);
Packit Service 82fcde
  return (di & 0x7fffffffffffffffull) == 0x7ff0000000000000ull;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static __always_inline int
Packit Service 82fcde
__finite_inl (double d)
Packit Service 82fcde
{
Packit Service 82fcde
  uint64_t di;
Packit Service 82fcde
  EXTRACT_WORDS64 (di, d);
Packit Service 82fcde
  return (di & 0x7fffffffffffffffull) < 0x7ff0000000000000ull;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#define __isnormal_inl(X) (__fpclassify (X) == FP_NORMAL)
Packit Service 82fcde
Packit Service 82fcde
/* Inlines for the builtin functions.  */
Packit Service 82fcde
Packit Service 82fcde
#define __isnan_builtin(X) __builtin_isnan (X)
Packit Service 82fcde
#define __isinf_ns_builtin(X) __builtin_isinf (X)
Packit Service 82fcde
#define __isinf_builtin(X) __builtin_isinf_sign (X)
Packit Service 82fcde
#define __isfinite_builtin(X) __builtin_isfinite (X)
Packit Service 82fcde
#define __isnormal_builtin(X) __builtin_isnormal (X)
Packit Service 82fcde
#define __fpclassify_builtin(X) __builtin_fpclassify (FP_NAN, FP_INFINITE,  \
Packit Service 82fcde
				  FP_NORMAL, FP_SUBNORMAL, FP_ZERO, (X))
Packit Service 82fcde
Packit Service 82fcde
static double __attribute ((noinline))
Packit Service 82fcde
kernel_standard (double x, double y, int z)
Packit Service 82fcde
{
Packit Service 82fcde
  return x * y + z;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
volatile double rem1 = 2.5;
Packit Service 82fcde
Packit Service 82fcde
static __always_inline double
Packit Service 82fcde
remainder_test1 (double x)
Packit Service 82fcde
{
Packit Service 82fcde
  double y = rem1;
Packit Service 82fcde
  if (((__builtin_expect (y == 0.0, 0) && !__isnan_inl (x))
Packit Service 82fcde
	|| (__builtin_expect (__isinf_ns2 (x), 0) && !__isnan_inl (y))))
Packit Service 82fcde
    return kernel_standard (x, y, 10);
Packit Service 82fcde
Packit Service 82fcde
  return remainder (x, y);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static __always_inline double
Packit Service 82fcde
remainder_test2 (double x)
Packit Service 82fcde
{
Packit Service 82fcde
  double y = rem1;
Packit Service 82fcde
  if (((__builtin_expect (y == 0.0, 0) && !__builtin_isnan (x))
Packit Service 82fcde
	|| (__builtin_expect (__builtin_isinf (x), 0) && !__builtin_isnan (y))))
Packit Service 82fcde
    return kernel_standard (x, y, 10);
Packit Service 82fcde
Packit Service 82fcde
  return remainder (x, y);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Create test functions for each possibility.  */
Packit Service 82fcde
Packit Service 82fcde
BOOLTEST (__isnan)
Packit Service 82fcde
BOOLTEST (__isnan_inl)
Packit Service 82fcde
BOOLTEST (__isnan_builtin)
Packit Service 82fcde
BOOLTEST (isnan)
Packit Service 82fcde
Packit Service 82fcde
BOOLTEST (__isinf)
Packit Service 82fcde
BOOLTEST (__isinf_builtin)
Packit Service 82fcde
BOOLTEST (__isinf_ns2)
Packit Service 82fcde
BOOLTEST (__isinf_ns_builtin)
Packit Service 82fcde
BOOLTEST (isinf)
Packit Service 82fcde
Packit Service 82fcde
BOOLTEST (__finite)
Packit Service 82fcde
BOOLTEST (__finite_inl)
Packit Service 82fcde
BOOLTEST (__isfinite_builtin)
Packit Service 82fcde
BOOLTEST (isfinite)
Packit Service 82fcde
Packit Service 82fcde
BOOLTEST (__isnormal_inl)
Packit Service 82fcde
BOOLTEST (__isnormal_builtin)
Packit Service 82fcde
BOOLTEST (isnormal)
Packit Service 82fcde
Packit Service 82fcde
VALUETEST (__fpclassify)
Packit Service 82fcde
VALUETEST (__fpclassify_builtin)
Packit Service 82fcde
VALUETEST (fpclassify)
Packit Service 82fcde
Packit Service 82fcde
VALUETEST (remainder_test1)
Packit Service 82fcde
VALUETEST (remainder_test2)
Packit Service 82fcde
Packit Service 82fcde
typedef int (*proto_t) (volatile double *p, size_t n, size_t iters);
Packit Service 82fcde
Packit Service 82fcde
typedef struct
Packit Service 82fcde
{
Packit Service 82fcde
  const char *name;
Packit Service 82fcde
  proto_t fn;
Packit Service 82fcde
} impl_t;
Packit Service 82fcde
Packit Service 82fcde
#define IMPL(name) { #name, name ## _t }
Packit Service 82fcde
Packit Service 82fcde
static impl_t test_list[] =
Packit Service 82fcde
{
Packit Service 82fcde
  IMPL (__isnan),
Packit Service 82fcde
  IMPL (__isnan_inl),
Packit Service 82fcde
  IMPL (__isnan_builtin),
Packit Service 82fcde
  IMPL (isnan),
Packit Service 82fcde
Packit Service 82fcde
  IMPL (__isinf),
Packit Service 82fcde
  IMPL (__isinf_ns2),
Packit Service 82fcde
  IMPL (__isinf_ns_builtin),
Packit Service 82fcde
  IMPL (__isinf_builtin),
Packit Service 82fcde
  IMPL (isinf),
Packit Service 82fcde
Packit Service 82fcde
  IMPL (__finite),
Packit Service 82fcde
  IMPL (__finite_inl),
Packit Service 82fcde
  IMPL (__isfinite_builtin),
Packit Service 82fcde
  IMPL (isfinite),
Packit Service 82fcde
Packit Service 82fcde
  IMPL (__isnormal_inl),
Packit Service 82fcde
  IMPL (__isnormal_builtin),
Packit Service 82fcde
  IMPL (isnormal),
Packit Service 82fcde
Packit Service 82fcde
  IMPL (__fpclassify),
Packit Service 82fcde
  IMPL (__fpclassify_builtin),
Packit Service 82fcde
  IMPL (fpclassify),
Packit Service 82fcde
Packit Service 82fcde
  IMPL (remainder_test1),
Packit Service 82fcde
  IMPL (remainder_test2)
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
do_one_test (json_ctx_t *json_ctx, proto_t test_fn, volatile double *arr,
Packit Service 82fcde
	     size_t len, const char *testname)
Packit Service 82fcde
{
Packit Service 82fcde
  size_t iters = 500;
Packit Service 82fcde
  timing_t start, stop, cur;
Packit Service 82fcde
Packit Service 82fcde
  json_attr_object_begin (json_ctx, testname);
Packit Service 82fcde
Packit Service 82fcde
  TIMING_NOW (start);
Packit Service 82fcde
  test_fn (arr, len, iters);
Packit Service 82fcde
  TIMING_NOW (stop);
Packit Service 82fcde
  TIMING_DIFF (cur, start, stop);
Packit Service 82fcde
Packit Service 82fcde
  json_attr_double (json_ctx, "duration", cur);
Packit Service 82fcde
  json_attr_double (json_ctx, "iterations", iters);
Packit Service 82fcde
  json_attr_double (json_ctx, "mean", cur / iters);
Packit Service 82fcde
  json_attr_object_end (json_ctx);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static volatile double arr1[SIZE];
Packit Service 82fcde
static volatile double arr2[SIZE];
Packit Service 82fcde
Packit Service 82fcde
int
Packit Service 82fcde
test_main (void)
Packit Service 82fcde
{
Packit Service 82fcde
  json_ctx_t json_ctx;
Packit Service 82fcde
  size_t i;
Packit Service 82fcde
Packit Service 82fcde
  bench_start ();
Packit Service 82fcde
Packit Service 82fcde
  json_init (&json_ctx, 2, stdout);
Packit Service 82fcde
  json_attr_object_begin (&json_ctx, TEST_NAME);
Packit Service 82fcde
Packit Service 82fcde
  /* Create 2 test arrays, one with 10% zeroes, 10% negative values,
Packit Service 82fcde
     79% positive values and 1% infinity/NaN.  The other contains
Packit Service 82fcde
     50% inf, 50% NaN.  This relies on rand behaving correctly.  */
Packit Service 82fcde
Packit Service 82fcde
  for (i = 0; i < SIZE; i++)
Packit Service 82fcde
    {
Packit Service 82fcde
      int x = rand () & 255;
Packit Service 82fcde
      arr1[i] = (x < 25) ? 0.0 : ((x < 50) ? -1 : 100);
Packit Service 82fcde
      if (x == 255) arr1[i] = __builtin_inf ();
Packit Service 82fcde
      if (x == 254) arr1[i] = __builtin_nan ("0");
Packit Service 82fcde
      arr2[i] = (x < 128) ? __builtin_inf () : __builtin_nan ("0");
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  for (i = 0; i < sizeof (test_list) / sizeof (test_list[0]); i++)
Packit Service 82fcde
    {
Packit Service 82fcde
      json_attr_object_begin (&json_ctx, test_list[i].name);
Packit Service 82fcde
      do_one_test (&json_ctx, test_list[i].fn, arr2, SIZE, "inf/nan");
Packit Service 82fcde
      json_attr_object_end (&json_ctx);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  for (i = 0; i < sizeof (test_list) / sizeof (test_list[0]); i++)
Packit Service 82fcde
    {
Packit Service 82fcde
      json_attr_object_begin (&json_ctx, test_list[i].name);
Packit Service 82fcde
      do_one_test (&json_ctx, test_list[i].fn, arr1, SIZE, "normal");
Packit Service 82fcde
      json_attr_object_end (&json_ctx);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  json_attr_object_end (&json_ctx);
Packit Service 82fcde
  return 0;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#include "bench-util.c"
Packit Service 82fcde
#include "../test-skeleton.c"