1bbbf1280Sopenharmony_ci/*
2bbbf1280Sopenharmony_ci * Microbenchmark for math functions.
3bbbf1280Sopenharmony_ci *
4bbbf1280Sopenharmony_ci * Copyright (c) 2018-2020, Arm Limited.
5bbbf1280Sopenharmony_ci * SPDX-License-Identifier: MIT
6bbbf1280Sopenharmony_ci */
7bbbf1280Sopenharmony_ci
8bbbf1280Sopenharmony_ci#undef _GNU_SOURCE
9bbbf1280Sopenharmony_ci#define _GNU_SOURCE 1
10bbbf1280Sopenharmony_ci#include <stdint.h>
11bbbf1280Sopenharmony_ci#include <stdlib.h>
12bbbf1280Sopenharmony_ci#include <stdio.h>
13bbbf1280Sopenharmony_ci#include <string.h>
14bbbf1280Sopenharmony_ci#include <time.h>
15bbbf1280Sopenharmony_ci#include <math.h>
16bbbf1280Sopenharmony_ci#include "mathlib.h"
17bbbf1280Sopenharmony_ci
18bbbf1280Sopenharmony_ci#ifndef WANT_VMATH
19bbbf1280Sopenharmony_ci/* Enable the build of vector math code.  */
20bbbf1280Sopenharmony_ci# define WANT_VMATH 1
21bbbf1280Sopenharmony_ci#endif
22bbbf1280Sopenharmony_ci
23bbbf1280Sopenharmony_ci/* Number of measurements, best result is reported.  */
24bbbf1280Sopenharmony_ci#define MEASURE 60
25bbbf1280Sopenharmony_ci/* Array size.  */
26bbbf1280Sopenharmony_ci#define N 8000
27bbbf1280Sopenharmony_ci/* Iterations over the array.  */
28bbbf1280Sopenharmony_ci#define ITER 125
29bbbf1280Sopenharmony_ci
30bbbf1280Sopenharmony_cistatic double *Trace;
31bbbf1280Sopenharmony_cistatic size_t trace_size;
32bbbf1280Sopenharmony_cistatic double A[N];
33bbbf1280Sopenharmony_cistatic float Af[N];
34bbbf1280Sopenharmony_cistatic long measurecount = MEASURE;
35bbbf1280Sopenharmony_cistatic long itercount = ITER;
36bbbf1280Sopenharmony_ci
37bbbf1280Sopenharmony_ci#if __aarch64__ && WANT_VMATH
38bbbf1280Sopenharmony_citypedef __f64x2_t v_double;
39bbbf1280Sopenharmony_ci
40bbbf1280Sopenharmony_ci#define v_double_len() 2
41bbbf1280Sopenharmony_ci
42bbbf1280Sopenharmony_cistatic inline v_double
43bbbf1280Sopenharmony_civ_double_load (const double *p)
44bbbf1280Sopenharmony_ci{
45bbbf1280Sopenharmony_ci  return (v_double){p[0], p[1]};
46bbbf1280Sopenharmony_ci}
47bbbf1280Sopenharmony_ci
48bbbf1280Sopenharmony_cistatic inline v_double
49bbbf1280Sopenharmony_civ_double_dup (double x)
50bbbf1280Sopenharmony_ci{
51bbbf1280Sopenharmony_ci  return (v_double){x, x};
52bbbf1280Sopenharmony_ci}
53bbbf1280Sopenharmony_ci
54bbbf1280Sopenharmony_citypedef __f32x4_t v_float;
55bbbf1280Sopenharmony_ci
56bbbf1280Sopenharmony_ci#define v_float_len() 4
57bbbf1280Sopenharmony_ci
58bbbf1280Sopenharmony_cistatic inline v_float
59bbbf1280Sopenharmony_civ_float_load (const float *p)
60bbbf1280Sopenharmony_ci{
61bbbf1280Sopenharmony_ci  return (v_float){p[0], p[1], p[2], p[3]};
62bbbf1280Sopenharmony_ci}
63bbbf1280Sopenharmony_ci
64bbbf1280Sopenharmony_cistatic inline v_float
65bbbf1280Sopenharmony_civ_float_dup (float x)
66bbbf1280Sopenharmony_ci{
67bbbf1280Sopenharmony_ci  return (v_float){x, x, x, x};
68bbbf1280Sopenharmony_ci}
69bbbf1280Sopenharmony_ci#else
70bbbf1280Sopenharmony_ci/* dummy definitions to make things compile.  */
71bbbf1280Sopenharmony_citypedef double v_double;
72bbbf1280Sopenharmony_citypedef float v_float;
73bbbf1280Sopenharmony_ci#define v_double_len(x) 1
74bbbf1280Sopenharmony_ci#define v_double_load(x) (x)[0]
75bbbf1280Sopenharmony_ci#define v_double_dup(x) (x)
76bbbf1280Sopenharmony_ci#define v_float_len(x) 1
77bbbf1280Sopenharmony_ci#define v_float_load(x) (x)[0]
78bbbf1280Sopenharmony_ci#define v_float_dup(x) (x)
79bbbf1280Sopenharmony_ci#endif
80bbbf1280Sopenharmony_ci
81bbbf1280Sopenharmony_cistatic double
82bbbf1280Sopenharmony_cidummy (double x)
83bbbf1280Sopenharmony_ci{
84bbbf1280Sopenharmony_ci  return x;
85bbbf1280Sopenharmony_ci}
86bbbf1280Sopenharmony_ci
87bbbf1280Sopenharmony_cistatic float
88bbbf1280Sopenharmony_cidummyf (float x)
89bbbf1280Sopenharmony_ci{
90bbbf1280Sopenharmony_ci  return x;
91bbbf1280Sopenharmony_ci}
92bbbf1280Sopenharmony_ci
93bbbf1280Sopenharmony_ci#if WANT_VMATH
94bbbf1280Sopenharmony_ci#if __aarch64__
95bbbf1280Sopenharmony_cistatic v_double
96bbbf1280Sopenharmony_ci__v_dummy (v_double x)
97bbbf1280Sopenharmony_ci{
98bbbf1280Sopenharmony_ci  return x;
99bbbf1280Sopenharmony_ci}
100bbbf1280Sopenharmony_ci
101bbbf1280Sopenharmony_cistatic v_float
102bbbf1280Sopenharmony_ci__v_dummyf (v_float x)
103bbbf1280Sopenharmony_ci{
104bbbf1280Sopenharmony_ci  return x;
105bbbf1280Sopenharmony_ci}
106bbbf1280Sopenharmony_ci
107bbbf1280Sopenharmony_ci#ifdef __vpcs
108bbbf1280Sopenharmony_ci__vpcs static v_double
109bbbf1280Sopenharmony_ci__vn_dummy (v_double x)
110bbbf1280Sopenharmony_ci{
111bbbf1280Sopenharmony_ci  return x;
112bbbf1280Sopenharmony_ci}
113bbbf1280Sopenharmony_ci
114bbbf1280Sopenharmony_ci__vpcs static v_float
115bbbf1280Sopenharmony_ci__vn_dummyf (v_float x)
116bbbf1280Sopenharmony_ci{
117bbbf1280Sopenharmony_ci  return x;
118bbbf1280Sopenharmony_ci}
119bbbf1280Sopenharmony_ci
120bbbf1280Sopenharmony_ci__vpcs static v_float
121bbbf1280Sopenharmony_cixy__vn_powf (v_float x)
122bbbf1280Sopenharmony_ci{
123bbbf1280Sopenharmony_ci  return __vn_powf (x, x);
124bbbf1280Sopenharmony_ci}
125bbbf1280Sopenharmony_ci
126bbbf1280Sopenharmony_ci__vpcs static v_float
127bbbf1280Sopenharmony_cixy_Z_powf (v_float x)
128bbbf1280Sopenharmony_ci{
129bbbf1280Sopenharmony_ci  return _ZGVnN4vv_powf (x, x);
130bbbf1280Sopenharmony_ci}
131bbbf1280Sopenharmony_ci
132bbbf1280Sopenharmony_ci__vpcs static v_double
133bbbf1280Sopenharmony_cixy__vn_pow (v_double x)
134bbbf1280Sopenharmony_ci{
135bbbf1280Sopenharmony_ci  return __vn_pow (x, x);
136bbbf1280Sopenharmony_ci}
137bbbf1280Sopenharmony_ci
138bbbf1280Sopenharmony_ci__vpcs static v_double
139bbbf1280Sopenharmony_cixy_Z_pow (v_double x)
140bbbf1280Sopenharmony_ci{
141bbbf1280Sopenharmony_ci  return _ZGVnN2vv_pow (x, x);
142bbbf1280Sopenharmony_ci}
143bbbf1280Sopenharmony_ci#endif
144bbbf1280Sopenharmony_ci
145bbbf1280Sopenharmony_cistatic v_float
146bbbf1280Sopenharmony_cixy__v_powf (v_float x)
147bbbf1280Sopenharmony_ci{
148bbbf1280Sopenharmony_ci  return __v_powf (x, x);
149bbbf1280Sopenharmony_ci}
150bbbf1280Sopenharmony_ci
151bbbf1280Sopenharmony_cistatic v_double
152bbbf1280Sopenharmony_cixy__v_pow (v_double x)
153bbbf1280Sopenharmony_ci{
154bbbf1280Sopenharmony_ci  return __v_pow (x, x);
155bbbf1280Sopenharmony_ci}
156bbbf1280Sopenharmony_ci#endif
157bbbf1280Sopenharmony_ci
158bbbf1280Sopenharmony_cistatic float
159bbbf1280Sopenharmony_cixy__s_powf (float x)
160bbbf1280Sopenharmony_ci{
161bbbf1280Sopenharmony_ci  return __s_powf (x, x);
162bbbf1280Sopenharmony_ci}
163bbbf1280Sopenharmony_ci
164bbbf1280Sopenharmony_cistatic double
165bbbf1280Sopenharmony_cixy__s_pow (double x)
166bbbf1280Sopenharmony_ci{
167bbbf1280Sopenharmony_ci  return __s_pow (x, x);
168bbbf1280Sopenharmony_ci}
169bbbf1280Sopenharmony_ci#endif
170bbbf1280Sopenharmony_ci
171bbbf1280Sopenharmony_cistatic double
172bbbf1280Sopenharmony_cixypow (double x)
173bbbf1280Sopenharmony_ci{
174bbbf1280Sopenharmony_ci  return pow (x, x);
175bbbf1280Sopenharmony_ci}
176bbbf1280Sopenharmony_ci
177bbbf1280Sopenharmony_cistatic float
178bbbf1280Sopenharmony_cixypowf (float x)
179bbbf1280Sopenharmony_ci{
180bbbf1280Sopenharmony_ci  return powf (x, x);
181bbbf1280Sopenharmony_ci}
182bbbf1280Sopenharmony_ci
183bbbf1280Sopenharmony_cistatic double
184bbbf1280Sopenharmony_cixpow (double x)
185bbbf1280Sopenharmony_ci{
186bbbf1280Sopenharmony_ci  return pow (x, 23.4);
187bbbf1280Sopenharmony_ci}
188bbbf1280Sopenharmony_ci
189bbbf1280Sopenharmony_cistatic float
190bbbf1280Sopenharmony_cixpowf (float x)
191bbbf1280Sopenharmony_ci{
192bbbf1280Sopenharmony_ci  return powf (x, 23.4f);
193bbbf1280Sopenharmony_ci}
194bbbf1280Sopenharmony_ci
195bbbf1280Sopenharmony_cistatic double
196bbbf1280Sopenharmony_ciypow (double x)
197bbbf1280Sopenharmony_ci{
198bbbf1280Sopenharmony_ci  return pow (2.34, x);
199bbbf1280Sopenharmony_ci}
200bbbf1280Sopenharmony_ci
201bbbf1280Sopenharmony_cistatic float
202bbbf1280Sopenharmony_ciypowf (float x)
203bbbf1280Sopenharmony_ci{
204bbbf1280Sopenharmony_ci  return powf (2.34f, x);
205bbbf1280Sopenharmony_ci}
206bbbf1280Sopenharmony_ci
207bbbf1280Sopenharmony_cistatic float
208bbbf1280Sopenharmony_cisincosf_wrap (float x)
209bbbf1280Sopenharmony_ci{
210bbbf1280Sopenharmony_ci  float s, c;
211bbbf1280Sopenharmony_ci  sincosf (x, &s, &c);
212bbbf1280Sopenharmony_ci  return s + c;
213bbbf1280Sopenharmony_ci}
214bbbf1280Sopenharmony_ci
215bbbf1280Sopenharmony_cistatic const struct fun
216bbbf1280Sopenharmony_ci{
217bbbf1280Sopenharmony_ci  const char *name;
218bbbf1280Sopenharmony_ci  int prec;
219bbbf1280Sopenharmony_ci  int vec;
220bbbf1280Sopenharmony_ci  double lo;
221bbbf1280Sopenharmony_ci  double hi;
222bbbf1280Sopenharmony_ci  union
223bbbf1280Sopenharmony_ci  {
224bbbf1280Sopenharmony_ci    double (*d) (double);
225bbbf1280Sopenharmony_ci    float (*f) (float);
226bbbf1280Sopenharmony_ci    v_double (*vd) (v_double);
227bbbf1280Sopenharmony_ci    v_float (*vf) (v_float);
228bbbf1280Sopenharmony_ci#ifdef __vpcs
229bbbf1280Sopenharmony_ci    __vpcs v_double (*vnd) (v_double);
230bbbf1280Sopenharmony_ci    __vpcs v_float (*vnf) (v_float);
231bbbf1280Sopenharmony_ci#endif
232bbbf1280Sopenharmony_ci  } fun;
233bbbf1280Sopenharmony_ci} funtab[] = {
234bbbf1280Sopenharmony_ci#define D(func, lo, hi) {#func, 'd', 0, lo, hi, {.d = func}},
235bbbf1280Sopenharmony_ci#define F(func, lo, hi) {#func, 'f', 0, lo, hi, {.f = func}},
236bbbf1280Sopenharmony_ci#define VD(func, lo, hi) {#func, 'd', 'v', lo, hi, {.vd = func}},
237bbbf1280Sopenharmony_ci#define VF(func, lo, hi) {#func, 'f', 'v', lo, hi, {.vf = func}},
238bbbf1280Sopenharmony_ci#define VND(func, lo, hi) {#func, 'd', 'n', lo, hi, {.vnd = func}},
239bbbf1280Sopenharmony_ci#define VNF(func, lo, hi) {#func, 'f', 'n', lo, hi, {.vnf = func}},
240bbbf1280Sopenharmony_ciD (dummy, 1.0, 2.0)
241bbbf1280Sopenharmony_ciD (exp, -9.9, 9.9)
242bbbf1280Sopenharmony_ciD (exp, 0.5, 1.0)
243bbbf1280Sopenharmony_ciD (exp2, -9.9, 9.9)
244bbbf1280Sopenharmony_ciD (log, 0.01, 11.1)
245bbbf1280Sopenharmony_ciD (log, 0.999, 1.001)
246bbbf1280Sopenharmony_ciD (log2, 0.01, 11.1)
247bbbf1280Sopenharmony_ciD (log2, 0.999, 1.001)
248bbbf1280Sopenharmony_ci{"pow", 'd', 0, 0.01, 11.1, {.d = xypow}},
249bbbf1280Sopenharmony_ciD (xpow, 0.01, 11.1)
250bbbf1280Sopenharmony_ciD (ypow, -9.9, 9.9)
251bbbf1280Sopenharmony_ciD (erf, -6.0, 6.0)
252bbbf1280Sopenharmony_ci
253bbbf1280Sopenharmony_ciF (dummyf, 1.0, 2.0)
254bbbf1280Sopenharmony_ciF (expf, -9.9, 9.9)
255bbbf1280Sopenharmony_ciF (exp2f, -9.9, 9.9)
256bbbf1280Sopenharmony_ciF (logf, 0.01, 11.1)
257bbbf1280Sopenharmony_ciF (log2f, 0.01, 11.1)
258bbbf1280Sopenharmony_ci{"powf", 'f', 0, 0.01, 11.1, {.f = xypowf}},
259bbbf1280Sopenharmony_ciF (xpowf, 0.01, 11.1)
260bbbf1280Sopenharmony_ciF (ypowf, -9.9, 9.9)
261bbbf1280Sopenharmony_ci{"sincosf", 'f', 0, 0.1, 0.7, {.f = sincosf_wrap}},
262bbbf1280Sopenharmony_ci{"sincosf", 'f', 0, 0.8, 3.1, {.f = sincosf_wrap}},
263bbbf1280Sopenharmony_ci{"sincosf", 'f', 0, -3.1, 3.1, {.f = sincosf_wrap}},
264bbbf1280Sopenharmony_ci{"sincosf", 'f', 0, 3.3, 33.3, {.f = sincosf_wrap}},
265bbbf1280Sopenharmony_ci{"sincosf", 'f', 0, 100, 1000, {.f = sincosf_wrap}},
266bbbf1280Sopenharmony_ci{"sincosf", 'f', 0, 1e6, 1e32, {.f = sincosf_wrap}},
267bbbf1280Sopenharmony_ciF (sinf, 0.1, 0.7)
268bbbf1280Sopenharmony_ciF (sinf, 0.8, 3.1)
269bbbf1280Sopenharmony_ciF (sinf, -3.1, 3.1)
270bbbf1280Sopenharmony_ciF (sinf, 3.3, 33.3)
271bbbf1280Sopenharmony_ciF (sinf, 100, 1000)
272bbbf1280Sopenharmony_ciF (sinf, 1e6, 1e32)
273bbbf1280Sopenharmony_ciF (cosf, 0.1, 0.7)
274bbbf1280Sopenharmony_ciF (cosf, 0.8, 3.1)
275bbbf1280Sopenharmony_ciF (cosf, -3.1, 3.1)
276bbbf1280Sopenharmony_ciF (cosf, 3.3, 33.3)
277bbbf1280Sopenharmony_ciF (cosf, 100, 1000)
278bbbf1280Sopenharmony_ciF (cosf, 1e6, 1e32)
279bbbf1280Sopenharmony_ciF (erff, -4.0, 4.0)
280bbbf1280Sopenharmony_ci#if WANT_VMATH
281bbbf1280Sopenharmony_ciD (__s_sin, -3.1, 3.1)
282bbbf1280Sopenharmony_ciD (__s_cos, -3.1, 3.1)
283bbbf1280Sopenharmony_ciD (__s_exp, -9.9, 9.9)
284bbbf1280Sopenharmony_ciD (__s_log, 0.01, 11.1)
285bbbf1280Sopenharmony_ci{"__s_pow", 'd', 0, 0.01, 11.1, {.d = xy__s_pow}},
286bbbf1280Sopenharmony_ciF (__s_expf, -9.9, 9.9)
287bbbf1280Sopenharmony_ciF (__s_expf_1u, -9.9, 9.9)
288bbbf1280Sopenharmony_ciF (__s_exp2f, -9.9, 9.9)
289bbbf1280Sopenharmony_ciF (__s_exp2f_1u, -9.9, 9.9)
290bbbf1280Sopenharmony_ciF (__s_logf, 0.01, 11.1)
291bbbf1280Sopenharmony_ci{"__s_powf", 'f', 0, 0.01, 11.1, {.f = xy__s_powf}},
292bbbf1280Sopenharmony_ciF (__s_sinf, -3.1, 3.1)
293bbbf1280Sopenharmony_ciF (__s_cosf, -3.1, 3.1)
294bbbf1280Sopenharmony_ci#if __aarch64__
295bbbf1280Sopenharmony_ciVD (__v_dummy, 1.0, 2.0)
296bbbf1280Sopenharmony_ciVD (__v_sin, -3.1, 3.1)
297bbbf1280Sopenharmony_ciVD (__v_cos, -3.1, 3.1)
298bbbf1280Sopenharmony_ciVD (__v_exp, -9.9, 9.9)
299bbbf1280Sopenharmony_ciVD (__v_log, 0.01, 11.1)
300bbbf1280Sopenharmony_ci{"__v_pow", 'd', 'v', 0.01, 11.1, {.vd = xy__v_pow}},
301bbbf1280Sopenharmony_ciVF (__v_dummyf, 1.0, 2.0)
302bbbf1280Sopenharmony_ciVF (__v_expf, -9.9, 9.9)
303bbbf1280Sopenharmony_ciVF (__v_expf_1u, -9.9, 9.9)
304bbbf1280Sopenharmony_ciVF (__v_exp2f, -9.9, 9.9)
305bbbf1280Sopenharmony_ciVF (__v_exp2f_1u, -9.9, 9.9)
306bbbf1280Sopenharmony_ciVF (__v_logf, 0.01, 11.1)
307bbbf1280Sopenharmony_ci{"__v_powf", 'f', 'v', 0.01, 11.1, {.vf = xy__v_powf}},
308bbbf1280Sopenharmony_ciVF (__v_sinf, -3.1, 3.1)
309bbbf1280Sopenharmony_ciVF (__v_cosf, -3.1, 3.1)
310bbbf1280Sopenharmony_ci#ifdef __vpcs
311bbbf1280Sopenharmony_ciVND (__vn_dummy, 1.0, 2.0)
312bbbf1280Sopenharmony_ciVND (__vn_exp, -9.9, 9.9)
313bbbf1280Sopenharmony_ciVND (_ZGVnN2v_exp, -9.9, 9.9)
314bbbf1280Sopenharmony_ciVND (__vn_log, 0.01, 11.1)
315bbbf1280Sopenharmony_ciVND (_ZGVnN2v_log, 0.01, 11.1)
316bbbf1280Sopenharmony_ci{"__vn_pow", 'd', 'n', 0.01, 11.1, {.vnd = xy__vn_pow}},
317bbbf1280Sopenharmony_ci{"_ZGVnN2vv_pow", 'd', 'n', 0.01, 11.1, {.vnd = xy_Z_pow}},
318bbbf1280Sopenharmony_ciVND (__vn_sin, -3.1, 3.1)
319bbbf1280Sopenharmony_ciVND (_ZGVnN2v_sin, -3.1, 3.1)
320bbbf1280Sopenharmony_ciVND (__vn_cos, -3.1, 3.1)
321bbbf1280Sopenharmony_ciVND (_ZGVnN2v_cos, -3.1, 3.1)
322bbbf1280Sopenharmony_ciVNF (__vn_dummyf, 1.0, 2.0)
323bbbf1280Sopenharmony_ciVNF (__vn_expf, -9.9, 9.9)
324bbbf1280Sopenharmony_ciVNF (_ZGVnN4v_expf, -9.9, 9.9)
325bbbf1280Sopenharmony_ciVNF (__vn_expf_1u, -9.9, 9.9)
326bbbf1280Sopenharmony_ciVNF (__vn_exp2f, -9.9, 9.9)
327bbbf1280Sopenharmony_ciVNF (_ZGVnN4v_exp2f, -9.9, 9.9)
328bbbf1280Sopenharmony_ciVNF (__vn_exp2f_1u, -9.9, 9.9)
329bbbf1280Sopenharmony_ciVNF (__vn_logf, 0.01, 11.1)
330bbbf1280Sopenharmony_ciVNF (_ZGVnN4v_logf, 0.01, 11.1)
331bbbf1280Sopenharmony_ci{"__vn_powf", 'f', 'n', 0.01, 11.1, {.vnf = xy__vn_powf}},
332bbbf1280Sopenharmony_ci{"_ZGVnN4vv_powf", 'f', 'n', 0.01, 11.1, {.vnf = xy_Z_powf}},
333bbbf1280Sopenharmony_ciVNF (__vn_sinf, -3.1, 3.1)
334bbbf1280Sopenharmony_ciVNF (_ZGVnN4v_sinf, -3.1, 3.1)
335bbbf1280Sopenharmony_ciVNF (__vn_cosf, -3.1, 3.1)
336bbbf1280Sopenharmony_ciVNF (_ZGVnN4v_cosf, -3.1, 3.1)
337bbbf1280Sopenharmony_ci#endif
338bbbf1280Sopenharmony_ci#endif
339bbbf1280Sopenharmony_ci#endif
340bbbf1280Sopenharmony_ci{0},
341bbbf1280Sopenharmony_ci#undef F
342bbbf1280Sopenharmony_ci#undef D
343bbbf1280Sopenharmony_ci#undef VF
344bbbf1280Sopenharmony_ci#undef VD
345bbbf1280Sopenharmony_ci#undef VNF
346bbbf1280Sopenharmony_ci#undef VND
347bbbf1280Sopenharmony_ci};
348bbbf1280Sopenharmony_ci
349bbbf1280Sopenharmony_cistatic void
350bbbf1280Sopenharmony_cigen_linear (double lo, double hi)
351bbbf1280Sopenharmony_ci{
352bbbf1280Sopenharmony_ci  for (int i = 0; i < N; i++)
353bbbf1280Sopenharmony_ci    A[i] = (lo * (N - i) + hi * i) / N;
354bbbf1280Sopenharmony_ci}
355bbbf1280Sopenharmony_ci
356bbbf1280Sopenharmony_cistatic void
357bbbf1280Sopenharmony_cigenf_linear (double lo, double hi)
358bbbf1280Sopenharmony_ci{
359bbbf1280Sopenharmony_ci  for (int i = 0; i < N; i++)
360bbbf1280Sopenharmony_ci    Af[i] = (float)(lo * (N - i) + hi * i) / N;
361bbbf1280Sopenharmony_ci}
362bbbf1280Sopenharmony_ci
363bbbf1280Sopenharmony_cistatic inline double
364bbbf1280Sopenharmony_ciasdouble (uint64_t i)
365bbbf1280Sopenharmony_ci{
366bbbf1280Sopenharmony_ci  union
367bbbf1280Sopenharmony_ci  {
368bbbf1280Sopenharmony_ci    uint64_t i;
369bbbf1280Sopenharmony_ci    double f;
370bbbf1280Sopenharmony_ci  } u = {i};
371bbbf1280Sopenharmony_ci  return u.f;
372bbbf1280Sopenharmony_ci}
373bbbf1280Sopenharmony_ci
374bbbf1280Sopenharmony_cistatic uint64_t seed = 0x0123456789abcdef;
375bbbf1280Sopenharmony_ci
376bbbf1280Sopenharmony_cistatic double
377bbbf1280Sopenharmony_cifrand (double lo, double hi)
378bbbf1280Sopenharmony_ci{
379bbbf1280Sopenharmony_ci  seed = 6364136223846793005ULL * seed + 1;
380bbbf1280Sopenharmony_ci  return lo + (hi - lo) * (asdouble (seed >> 12 | 0x3ffULL << 52) - 1.0);
381bbbf1280Sopenharmony_ci}
382bbbf1280Sopenharmony_ci
383bbbf1280Sopenharmony_cistatic void
384bbbf1280Sopenharmony_cigen_rand (double lo, double hi)
385bbbf1280Sopenharmony_ci{
386bbbf1280Sopenharmony_ci  for (int i = 0; i < N; i++)
387bbbf1280Sopenharmony_ci    A[i] = frand (lo, hi);
388bbbf1280Sopenharmony_ci}
389bbbf1280Sopenharmony_ci
390bbbf1280Sopenharmony_cistatic void
391bbbf1280Sopenharmony_cigenf_rand (double lo, double hi)
392bbbf1280Sopenharmony_ci{
393bbbf1280Sopenharmony_ci  for (int i = 0; i < N; i++)
394bbbf1280Sopenharmony_ci    Af[i] = (float)frand (lo, hi);
395bbbf1280Sopenharmony_ci}
396bbbf1280Sopenharmony_ci
397bbbf1280Sopenharmony_cistatic void
398bbbf1280Sopenharmony_cigen_trace (int index)
399bbbf1280Sopenharmony_ci{
400bbbf1280Sopenharmony_ci  for (int i = 0; i < N; i++)
401bbbf1280Sopenharmony_ci    A[i] = Trace[index + i];
402bbbf1280Sopenharmony_ci}
403bbbf1280Sopenharmony_ci
404bbbf1280Sopenharmony_cistatic void
405bbbf1280Sopenharmony_cigenf_trace (int index)
406bbbf1280Sopenharmony_ci{
407bbbf1280Sopenharmony_ci  for (int i = 0; i < N; i++)
408bbbf1280Sopenharmony_ci    Af[i] = (float)Trace[index + i];
409bbbf1280Sopenharmony_ci}
410bbbf1280Sopenharmony_ci
411bbbf1280Sopenharmony_cistatic void
412bbbf1280Sopenharmony_cirun_thruput (double f (double))
413bbbf1280Sopenharmony_ci{
414bbbf1280Sopenharmony_ci  for (int i = 0; i < N; i++)
415bbbf1280Sopenharmony_ci    f (A[i]);
416bbbf1280Sopenharmony_ci}
417bbbf1280Sopenharmony_ci
418bbbf1280Sopenharmony_cistatic void
419bbbf1280Sopenharmony_cirunf_thruput (float f (float))
420bbbf1280Sopenharmony_ci{
421bbbf1280Sopenharmony_ci  for (int i = 0; i < N; i++)
422bbbf1280Sopenharmony_ci    f (Af[i]);
423bbbf1280Sopenharmony_ci}
424bbbf1280Sopenharmony_ci
425bbbf1280Sopenharmony_civolatile double zero = 0;
426bbbf1280Sopenharmony_ci
427bbbf1280Sopenharmony_cistatic void
428bbbf1280Sopenharmony_cirun_latency (double f (double))
429bbbf1280Sopenharmony_ci{
430bbbf1280Sopenharmony_ci  double z = zero;
431bbbf1280Sopenharmony_ci  double prev = z;
432bbbf1280Sopenharmony_ci  for (int i = 0; i < N; i++)
433bbbf1280Sopenharmony_ci    prev = f (A[i] + prev * z);
434bbbf1280Sopenharmony_ci}
435bbbf1280Sopenharmony_ci
436bbbf1280Sopenharmony_cistatic void
437bbbf1280Sopenharmony_cirunf_latency (float f (float))
438bbbf1280Sopenharmony_ci{
439bbbf1280Sopenharmony_ci  float z = (float)zero;
440bbbf1280Sopenharmony_ci  float prev = z;
441bbbf1280Sopenharmony_ci  for (int i = 0; i < N; i++)
442bbbf1280Sopenharmony_ci    prev = f (Af[i] + prev * z);
443bbbf1280Sopenharmony_ci}
444bbbf1280Sopenharmony_ci
445bbbf1280Sopenharmony_cistatic void
446bbbf1280Sopenharmony_cirun_v_thruput (v_double f (v_double))
447bbbf1280Sopenharmony_ci{
448bbbf1280Sopenharmony_ci  for (int i = 0; i < N; i += v_double_len ())
449bbbf1280Sopenharmony_ci    f (v_double_load (A+i));
450bbbf1280Sopenharmony_ci}
451bbbf1280Sopenharmony_ci
452bbbf1280Sopenharmony_cistatic void
453bbbf1280Sopenharmony_cirunf_v_thruput (v_float f (v_float))
454bbbf1280Sopenharmony_ci{
455bbbf1280Sopenharmony_ci  for (int i = 0; i < N; i += v_float_len ())
456bbbf1280Sopenharmony_ci    f (v_float_load (Af+i));
457bbbf1280Sopenharmony_ci}
458bbbf1280Sopenharmony_ci
459bbbf1280Sopenharmony_cistatic void
460bbbf1280Sopenharmony_cirun_v_latency (v_double f (v_double))
461bbbf1280Sopenharmony_ci{
462bbbf1280Sopenharmony_ci  v_double z = v_double_dup (zero);
463bbbf1280Sopenharmony_ci  v_double prev = z;
464bbbf1280Sopenharmony_ci  for (int i = 0; i < N; i += v_double_len ())
465bbbf1280Sopenharmony_ci    prev = f (v_double_load (A+i) + prev * z);
466bbbf1280Sopenharmony_ci}
467bbbf1280Sopenharmony_ci
468bbbf1280Sopenharmony_cistatic void
469bbbf1280Sopenharmony_cirunf_v_latency (v_float f (v_float))
470bbbf1280Sopenharmony_ci{
471bbbf1280Sopenharmony_ci  v_float z = v_float_dup (zero);
472bbbf1280Sopenharmony_ci  v_float prev = z;
473bbbf1280Sopenharmony_ci  for (int i = 0; i < N; i += v_float_len ())
474bbbf1280Sopenharmony_ci    prev = f (v_float_load (Af+i) + prev * z);
475bbbf1280Sopenharmony_ci}
476bbbf1280Sopenharmony_ci
477bbbf1280Sopenharmony_ci#ifdef __vpcs
478bbbf1280Sopenharmony_cistatic void
479bbbf1280Sopenharmony_cirun_vn_thruput (__vpcs v_double f (v_double))
480bbbf1280Sopenharmony_ci{
481bbbf1280Sopenharmony_ci  for (int i = 0; i < N; i += v_double_len ())
482bbbf1280Sopenharmony_ci    f (v_double_load (A+i));
483bbbf1280Sopenharmony_ci}
484bbbf1280Sopenharmony_ci
485bbbf1280Sopenharmony_cistatic void
486bbbf1280Sopenharmony_cirunf_vn_thruput (__vpcs v_float f (v_float))
487bbbf1280Sopenharmony_ci{
488bbbf1280Sopenharmony_ci  for (int i = 0; i < N; i += v_float_len ())
489bbbf1280Sopenharmony_ci    f (v_float_load (Af+i));
490bbbf1280Sopenharmony_ci}
491bbbf1280Sopenharmony_ci
492bbbf1280Sopenharmony_cistatic void
493bbbf1280Sopenharmony_cirun_vn_latency (__vpcs v_double f (v_double))
494bbbf1280Sopenharmony_ci{
495bbbf1280Sopenharmony_ci  v_double z = v_double_dup (zero);
496bbbf1280Sopenharmony_ci  v_double prev = z;
497bbbf1280Sopenharmony_ci  for (int i = 0; i < N; i += v_double_len ())
498bbbf1280Sopenharmony_ci    prev = f (v_double_load (A+i) + prev * z);
499bbbf1280Sopenharmony_ci}
500bbbf1280Sopenharmony_ci
501bbbf1280Sopenharmony_cistatic void
502bbbf1280Sopenharmony_cirunf_vn_latency (__vpcs v_float f (v_float))
503bbbf1280Sopenharmony_ci{
504bbbf1280Sopenharmony_ci  v_float z = v_float_dup (zero);
505bbbf1280Sopenharmony_ci  v_float prev = z;
506bbbf1280Sopenharmony_ci  for (int i = 0; i < N; i += v_float_len ())
507bbbf1280Sopenharmony_ci    prev = f (v_float_load (Af+i) + prev * z);
508bbbf1280Sopenharmony_ci}
509bbbf1280Sopenharmony_ci#endif
510bbbf1280Sopenharmony_ci
511bbbf1280Sopenharmony_cistatic uint64_t
512bbbf1280Sopenharmony_citic (void)
513bbbf1280Sopenharmony_ci{
514bbbf1280Sopenharmony_ci  struct timespec ts;
515bbbf1280Sopenharmony_ci  if (clock_gettime (CLOCK_REALTIME, &ts))
516bbbf1280Sopenharmony_ci    abort ();
517bbbf1280Sopenharmony_ci  return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
518bbbf1280Sopenharmony_ci}
519bbbf1280Sopenharmony_ci
520bbbf1280Sopenharmony_ci#define TIMEIT(run, f) do { \
521bbbf1280Sopenharmony_ci  dt = -1; \
522bbbf1280Sopenharmony_ci  run (f); /* Warm up.  */ \
523bbbf1280Sopenharmony_ci  for (int j = 0; j < measurecount; j++) \
524bbbf1280Sopenharmony_ci    { \
525bbbf1280Sopenharmony_ci      uint64_t t0 = tic (); \
526bbbf1280Sopenharmony_ci      for (int i = 0; i < itercount; i++) \
527bbbf1280Sopenharmony_ci	run (f); \
528bbbf1280Sopenharmony_ci      uint64_t t1 = tic (); \
529bbbf1280Sopenharmony_ci      if (t1 - t0 < dt) \
530bbbf1280Sopenharmony_ci	dt = t1 - t0; \
531bbbf1280Sopenharmony_ci    } \
532bbbf1280Sopenharmony_ci} while (0)
533bbbf1280Sopenharmony_ci
534bbbf1280Sopenharmony_cistatic void
535bbbf1280Sopenharmony_cibench1 (const struct fun *f, int type, double lo, double hi)
536bbbf1280Sopenharmony_ci{
537bbbf1280Sopenharmony_ci  uint64_t dt = 0;
538bbbf1280Sopenharmony_ci  uint64_t ns100;
539bbbf1280Sopenharmony_ci  const char *s = type == 't' ? "rthruput" : "latency";
540bbbf1280Sopenharmony_ci  int vlen = 1;
541bbbf1280Sopenharmony_ci
542bbbf1280Sopenharmony_ci  if (f->vec && f->prec == 'd')
543bbbf1280Sopenharmony_ci    vlen = v_double_len();
544bbbf1280Sopenharmony_ci  else if (f->vec && f->prec == 'f')
545bbbf1280Sopenharmony_ci    vlen = v_float_len();
546bbbf1280Sopenharmony_ci
547bbbf1280Sopenharmony_ci  if (f->prec == 'd' && type == 't' && f->vec == 0)
548bbbf1280Sopenharmony_ci    TIMEIT (run_thruput, f->fun.d);
549bbbf1280Sopenharmony_ci  else if (f->prec == 'd' && type == 'l' && f->vec == 0)
550bbbf1280Sopenharmony_ci    TIMEIT (run_latency, f->fun.d);
551bbbf1280Sopenharmony_ci  else if (f->prec == 'f' && type == 't' && f->vec == 0)
552bbbf1280Sopenharmony_ci    TIMEIT (runf_thruput, f->fun.f);
553bbbf1280Sopenharmony_ci  else if (f->prec == 'f' && type == 'l' && f->vec == 0)
554bbbf1280Sopenharmony_ci    TIMEIT (runf_latency, f->fun.f);
555bbbf1280Sopenharmony_ci  else if (f->prec == 'd' && type == 't' && f->vec == 'v')
556bbbf1280Sopenharmony_ci    TIMEIT (run_v_thruput, f->fun.vd);
557bbbf1280Sopenharmony_ci  else if (f->prec == 'd' && type == 'l' && f->vec == 'v')
558bbbf1280Sopenharmony_ci    TIMEIT (run_v_latency, f->fun.vd);
559bbbf1280Sopenharmony_ci  else if (f->prec == 'f' && type == 't' && f->vec == 'v')
560bbbf1280Sopenharmony_ci    TIMEIT (runf_v_thruput, f->fun.vf);
561bbbf1280Sopenharmony_ci  else if (f->prec == 'f' && type == 'l' && f->vec == 'v')
562bbbf1280Sopenharmony_ci    TIMEIT (runf_v_latency, f->fun.vf);
563bbbf1280Sopenharmony_ci#ifdef __vpcs
564bbbf1280Sopenharmony_ci  else if (f->prec == 'd' && type == 't' && f->vec == 'n')
565bbbf1280Sopenharmony_ci    TIMEIT (run_vn_thruput, f->fun.vnd);
566bbbf1280Sopenharmony_ci  else if (f->prec == 'd' && type == 'l' && f->vec == 'n')
567bbbf1280Sopenharmony_ci    TIMEIT (run_vn_latency, f->fun.vnd);
568bbbf1280Sopenharmony_ci  else if (f->prec == 'f' && type == 't' && f->vec == 'n')
569bbbf1280Sopenharmony_ci    TIMEIT (runf_vn_thruput, f->fun.vnf);
570bbbf1280Sopenharmony_ci  else if (f->prec == 'f' && type == 'l' && f->vec == 'n')
571bbbf1280Sopenharmony_ci    TIMEIT (runf_vn_latency, f->fun.vnf);
572bbbf1280Sopenharmony_ci#endif
573bbbf1280Sopenharmony_ci
574bbbf1280Sopenharmony_ci  if (type == 't')
575bbbf1280Sopenharmony_ci    {
576bbbf1280Sopenharmony_ci      ns100 = (100 * dt + itercount * N / 2) / (itercount * N);
577bbbf1280Sopenharmony_ci      printf ("%9s %8s: %4u.%02u ns/elem %10llu ns in [%g %g]\n", f->name, s,
578bbbf1280Sopenharmony_ci	      (unsigned) (ns100 / 100), (unsigned) (ns100 % 100),
579bbbf1280Sopenharmony_ci	      (unsigned long long) dt, lo, hi);
580bbbf1280Sopenharmony_ci    }
581bbbf1280Sopenharmony_ci  else if (type == 'l')
582bbbf1280Sopenharmony_ci    {
583bbbf1280Sopenharmony_ci      ns100 = (100 * dt + itercount * N / vlen / 2) / (itercount * N / vlen);
584bbbf1280Sopenharmony_ci      printf ("%9s %8s: %4u.%02u ns/call %10llu ns in [%g %g]\n", f->name, s,
585bbbf1280Sopenharmony_ci	      (unsigned) (ns100 / 100), (unsigned) (ns100 % 100),
586bbbf1280Sopenharmony_ci	      (unsigned long long) dt, lo, hi);
587bbbf1280Sopenharmony_ci    }
588bbbf1280Sopenharmony_ci  fflush (stdout);
589bbbf1280Sopenharmony_ci}
590bbbf1280Sopenharmony_ci
591bbbf1280Sopenharmony_cistatic void
592bbbf1280Sopenharmony_cibench (const struct fun *f, double lo, double hi, int type, int gen)
593bbbf1280Sopenharmony_ci{
594bbbf1280Sopenharmony_ci  if (f->prec == 'd' && gen == 'r')
595bbbf1280Sopenharmony_ci    gen_rand (lo, hi);
596bbbf1280Sopenharmony_ci  else if (f->prec == 'd' && gen == 'l')
597bbbf1280Sopenharmony_ci    gen_linear (lo, hi);
598bbbf1280Sopenharmony_ci  else if (f->prec == 'd' && gen == 't')
599bbbf1280Sopenharmony_ci    gen_trace (0);
600bbbf1280Sopenharmony_ci  else if (f->prec == 'f' && gen == 'r')
601bbbf1280Sopenharmony_ci    genf_rand (lo, hi);
602bbbf1280Sopenharmony_ci  else if (f->prec == 'f' && gen == 'l')
603bbbf1280Sopenharmony_ci    genf_linear (lo, hi);
604bbbf1280Sopenharmony_ci  else if (f->prec == 'f' && gen == 't')
605bbbf1280Sopenharmony_ci    genf_trace (0);
606bbbf1280Sopenharmony_ci
607bbbf1280Sopenharmony_ci  if (gen == 't')
608bbbf1280Sopenharmony_ci    hi = trace_size / N;
609bbbf1280Sopenharmony_ci
610bbbf1280Sopenharmony_ci  if (type == 'b' || type == 't')
611bbbf1280Sopenharmony_ci    bench1 (f, 't', lo, hi);
612bbbf1280Sopenharmony_ci
613bbbf1280Sopenharmony_ci  if (type == 'b' || type == 'l')
614bbbf1280Sopenharmony_ci    bench1 (f, 'l', lo, hi);
615bbbf1280Sopenharmony_ci
616bbbf1280Sopenharmony_ci  for (int i = N; i < trace_size; i += N)
617bbbf1280Sopenharmony_ci    {
618bbbf1280Sopenharmony_ci      if (f->prec == 'd')
619bbbf1280Sopenharmony_ci	gen_trace (i);
620bbbf1280Sopenharmony_ci      else
621bbbf1280Sopenharmony_ci	genf_trace (i);
622bbbf1280Sopenharmony_ci
623bbbf1280Sopenharmony_ci      lo = i / N;
624bbbf1280Sopenharmony_ci      if (type == 'b' || type == 't')
625bbbf1280Sopenharmony_ci	bench1 (f, 't', lo, hi);
626bbbf1280Sopenharmony_ci
627bbbf1280Sopenharmony_ci      if (type == 'b' || type == 'l')
628bbbf1280Sopenharmony_ci	bench1 (f, 'l', lo, hi);
629bbbf1280Sopenharmony_ci    }
630bbbf1280Sopenharmony_ci}
631bbbf1280Sopenharmony_ci
632bbbf1280Sopenharmony_cistatic void
633bbbf1280Sopenharmony_cireadtrace (const char *name)
634bbbf1280Sopenharmony_ci{
635bbbf1280Sopenharmony_ci	int n = 0;
636bbbf1280Sopenharmony_ci	FILE *f = strcmp (name, "-") == 0 ? stdin : fopen (name, "r");
637bbbf1280Sopenharmony_ci	if (!f)
638bbbf1280Sopenharmony_ci	  {
639bbbf1280Sopenharmony_ci	    printf ("openning \"%s\" failed: %m\n", name);
640bbbf1280Sopenharmony_ci	    exit (1);
641bbbf1280Sopenharmony_ci	  }
642bbbf1280Sopenharmony_ci	for (;;)
643bbbf1280Sopenharmony_ci	  {
644bbbf1280Sopenharmony_ci	    if (n >= trace_size)
645bbbf1280Sopenharmony_ci	      {
646bbbf1280Sopenharmony_ci		trace_size += N;
647bbbf1280Sopenharmony_ci		Trace = realloc (Trace, trace_size * sizeof (Trace[0]));
648bbbf1280Sopenharmony_ci		if (Trace == NULL)
649bbbf1280Sopenharmony_ci		  {
650bbbf1280Sopenharmony_ci		    printf ("out of memory\n");
651bbbf1280Sopenharmony_ci		    exit (1);
652bbbf1280Sopenharmony_ci		  }
653bbbf1280Sopenharmony_ci	      }
654bbbf1280Sopenharmony_ci	    if (fscanf (f, "%lf", Trace + n) != 1)
655bbbf1280Sopenharmony_ci	      break;
656bbbf1280Sopenharmony_ci	    n++;
657bbbf1280Sopenharmony_ci	  }
658bbbf1280Sopenharmony_ci	if (ferror (f) || n == 0)
659bbbf1280Sopenharmony_ci	  {
660bbbf1280Sopenharmony_ci	    printf ("reading \"%s\" failed: %m\n", name);
661bbbf1280Sopenharmony_ci	    exit (1);
662bbbf1280Sopenharmony_ci	  }
663bbbf1280Sopenharmony_ci	fclose (f);
664bbbf1280Sopenharmony_ci	if (n % N == 0)
665bbbf1280Sopenharmony_ci	  trace_size = n;
666bbbf1280Sopenharmony_ci	for (int i = 0; n < trace_size; n++, i++)
667bbbf1280Sopenharmony_ci	  Trace[n] = Trace[i];
668bbbf1280Sopenharmony_ci}
669bbbf1280Sopenharmony_ci
670bbbf1280Sopenharmony_cistatic void
671bbbf1280Sopenharmony_ciusage (void)
672bbbf1280Sopenharmony_ci{
673bbbf1280Sopenharmony_ci  printf ("usage: ./mathbench [-g rand|linear|trace] [-t latency|thruput|both] "
674bbbf1280Sopenharmony_ci	  "[-i low high] [-f tracefile] [-m measurements] [-c iterations] func "
675bbbf1280Sopenharmony_ci	  "[func2 ..]\n");
676bbbf1280Sopenharmony_ci  printf ("func:\n");
677bbbf1280Sopenharmony_ci  printf ("%7s [run all benchmarks]\n", "all");
678bbbf1280Sopenharmony_ci  for (const struct fun *f = funtab; f->name; f++)
679bbbf1280Sopenharmony_ci    printf ("%7s [low: %g high: %g]\n", f->name, f->lo, f->hi);
680bbbf1280Sopenharmony_ci  exit (1);
681bbbf1280Sopenharmony_ci}
682bbbf1280Sopenharmony_ci
683bbbf1280Sopenharmony_ciint
684bbbf1280Sopenharmony_cimain (int argc, char *argv[])
685bbbf1280Sopenharmony_ci{
686bbbf1280Sopenharmony_ci  int usergen = 0, gen = 'r', type = 'b', all = 0;
687bbbf1280Sopenharmony_ci  double lo = 0, hi = 0;
688bbbf1280Sopenharmony_ci  const char *tracefile = "-";
689bbbf1280Sopenharmony_ci
690bbbf1280Sopenharmony_ci  argv++;
691bbbf1280Sopenharmony_ci  argc--;
692bbbf1280Sopenharmony_ci  for (;;)
693bbbf1280Sopenharmony_ci    {
694bbbf1280Sopenharmony_ci      if (argc <= 0)
695bbbf1280Sopenharmony_ci	usage ();
696bbbf1280Sopenharmony_ci      if (argv[0][0] != '-')
697bbbf1280Sopenharmony_ci	break;
698bbbf1280Sopenharmony_ci      else if (argc >= 3 && strcmp (argv[0], "-i") == 0)
699bbbf1280Sopenharmony_ci	{
700bbbf1280Sopenharmony_ci	  usergen = 1;
701bbbf1280Sopenharmony_ci	  lo = strtod (argv[1], 0);
702bbbf1280Sopenharmony_ci	  hi = strtod (argv[2], 0);
703bbbf1280Sopenharmony_ci	  argv += 3;
704bbbf1280Sopenharmony_ci	  argc -= 3;
705bbbf1280Sopenharmony_ci	}
706bbbf1280Sopenharmony_ci      else if (argc >= 2 && strcmp (argv[0], "-m") == 0)
707bbbf1280Sopenharmony_ci	{
708bbbf1280Sopenharmony_ci	  measurecount = strtol (argv[1], 0, 0);
709bbbf1280Sopenharmony_ci	  argv += 2;
710bbbf1280Sopenharmony_ci	  argc -= 2;
711bbbf1280Sopenharmony_ci	}
712bbbf1280Sopenharmony_ci      else if (argc >= 2 && strcmp (argv[0], "-c") == 0)
713bbbf1280Sopenharmony_ci	{
714bbbf1280Sopenharmony_ci	  itercount = strtol (argv[1], 0, 0);
715bbbf1280Sopenharmony_ci	  argv += 2;
716bbbf1280Sopenharmony_ci	  argc -= 2;
717bbbf1280Sopenharmony_ci	}
718bbbf1280Sopenharmony_ci      else if (argc >= 2 && strcmp (argv[0], "-g") == 0)
719bbbf1280Sopenharmony_ci	{
720bbbf1280Sopenharmony_ci	  gen = argv[1][0];
721bbbf1280Sopenharmony_ci	  if (strchr ("rlt", gen) == 0)
722bbbf1280Sopenharmony_ci	    usage ();
723bbbf1280Sopenharmony_ci	  argv += 2;
724bbbf1280Sopenharmony_ci	  argc -= 2;
725bbbf1280Sopenharmony_ci	}
726bbbf1280Sopenharmony_ci      else if (argc >= 2 && strcmp (argv[0], "-f") == 0)
727bbbf1280Sopenharmony_ci	{
728bbbf1280Sopenharmony_ci	  gen = 't';  /* -f implies -g trace.  */
729bbbf1280Sopenharmony_ci	  tracefile = argv[1];
730bbbf1280Sopenharmony_ci	  argv += 2;
731bbbf1280Sopenharmony_ci	  argc -= 2;
732bbbf1280Sopenharmony_ci	}
733bbbf1280Sopenharmony_ci      else if (argc >= 2 && strcmp (argv[0], "-t") == 0)
734bbbf1280Sopenharmony_ci	{
735bbbf1280Sopenharmony_ci	  type = argv[1][0];
736bbbf1280Sopenharmony_ci	  if (strchr ("ltb", type) == 0)
737bbbf1280Sopenharmony_ci	    usage ();
738bbbf1280Sopenharmony_ci	  argv += 2;
739bbbf1280Sopenharmony_ci	  argc -= 2;
740bbbf1280Sopenharmony_ci	}
741bbbf1280Sopenharmony_ci      else
742bbbf1280Sopenharmony_ci	usage ();
743bbbf1280Sopenharmony_ci    }
744bbbf1280Sopenharmony_ci  if (gen == 't')
745bbbf1280Sopenharmony_ci    {
746bbbf1280Sopenharmony_ci      readtrace (tracefile);
747bbbf1280Sopenharmony_ci      lo = hi = 0;
748bbbf1280Sopenharmony_ci      usergen = 1;
749bbbf1280Sopenharmony_ci    }
750bbbf1280Sopenharmony_ci  while (argc > 0)
751bbbf1280Sopenharmony_ci    {
752bbbf1280Sopenharmony_ci      int found = 0;
753bbbf1280Sopenharmony_ci      all = strcmp (argv[0], "all") == 0;
754bbbf1280Sopenharmony_ci      for (const struct fun *f = funtab; f->name; f++)
755bbbf1280Sopenharmony_ci	if (all || strcmp (argv[0], f->name) == 0)
756bbbf1280Sopenharmony_ci	  {
757bbbf1280Sopenharmony_ci	    found = 1;
758bbbf1280Sopenharmony_ci	    if (!usergen)
759bbbf1280Sopenharmony_ci	      {
760bbbf1280Sopenharmony_ci		lo = f->lo;
761bbbf1280Sopenharmony_ci		hi = f->hi;
762bbbf1280Sopenharmony_ci	      }
763bbbf1280Sopenharmony_ci	    bench (f, lo, hi, type, gen);
764bbbf1280Sopenharmony_ci	    if (usergen && !all)
765bbbf1280Sopenharmony_ci	      break;
766bbbf1280Sopenharmony_ci	  }
767bbbf1280Sopenharmony_ci      if (!found)
768bbbf1280Sopenharmony_ci	printf ("unknown function: %s\n", argv[0]);
769bbbf1280Sopenharmony_ci      argv++;
770bbbf1280Sopenharmony_ci      argc--;
771bbbf1280Sopenharmony_ci    }
772bbbf1280Sopenharmony_ci  return 0;
773bbbf1280Sopenharmony_ci}
774