1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2015 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "bench/Benchmark.h" 9cb93a386Sopenharmony_ci#include "include/core/SkMatrix.h" 10cb93a386Sopenharmony_ci#include "include/core/SkPaint.h" 11cb93a386Sopenharmony_ci#include "include/core/SkString.h" 12cb93a386Sopenharmony_ci#include "include/private/SkColorData.h" 13cb93a386Sopenharmony_ci#include "include/private/SkFixed.h" 14cb93a386Sopenharmony_ci#include "include/utils/SkRandom.h" 15cb93a386Sopenharmony_ci#include "src/core/SkMathPriv.h" 16cb93a386Sopenharmony_ci 17cb93a386Sopenharmony_cistatic float sk_fsel(float pred, float result_ge, float result_lt) { 18cb93a386Sopenharmony_ci return pred >= 0 ? result_ge : result_lt; 19cb93a386Sopenharmony_ci} 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_cistatic float fast_floor(float x) { 22cb93a386Sopenharmony_ci// float big = sk_fsel(x, 0x1.0p+23, -0x1.0p+23); 23cb93a386Sopenharmony_ci float big = sk_fsel(x, (float)(1 << 23), -(float)(1 << 23)); 24cb93a386Sopenharmony_ci return (x + big) - big; 25cb93a386Sopenharmony_ci} 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_ciclass MathBench : public Benchmark { 28cb93a386Sopenharmony_ci enum { 29cb93a386Sopenharmony_ci kBuffer = 100, 30cb93a386Sopenharmony_ci }; 31cb93a386Sopenharmony_ci SkString fName; 32cb93a386Sopenharmony_ci float fSrc[kBuffer], fDst[kBuffer]; 33cb93a386Sopenharmony_cipublic: 34cb93a386Sopenharmony_ci MathBench(const char name[]) { 35cb93a386Sopenharmony_ci fName.printf("math_%s", name); 36cb93a386Sopenharmony_ci 37cb93a386Sopenharmony_ci SkRandom rand; 38cb93a386Sopenharmony_ci for (int i = 0; i < kBuffer; ++i) { 39cb93a386Sopenharmony_ci fSrc[i] = rand.nextSScalar1(); 40cb93a386Sopenharmony_ci } 41cb93a386Sopenharmony_ci } 42cb93a386Sopenharmony_ci 43cb93a386Sopenharmony_ci bool isSuitableFor(Backend backend) override { 44cb93a386Sopenharmony_ci return backend == kNonRendering_Backend; 45cb93a386Sopenharmony_ci } 46cb93a386Sopenharmony_ci 47cb93a386Sopenharmony_ci virtual void performTest(float* SK_RESTRICT dst, 48cb93a386Sopenharmony_ci const float* SK_RESTRICT src, 49cb93a386Sopenharmony_ci int count) = 0; 50cb93a386Sopenharmony_ci 51cb93a386Sopenharmony_ciprotected: 52cb93a386Sopenharmony_ci virtual int mulLoopCount() const { return 1; } 53cb93a386Sopenharmony_ci 54cb93a386Sopenharmony_ci const char* onGetName() override { 55cb93a386Sopenharmony_ci return fName.c_str(); 56cb93a386Sopenharmony_ci } 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_ci void onDraw(int loops, SkCanvas*) override { 59cb93a386Sopenharmony_ci int n = loops * this->mulLoopCount(); 60cb93a386Sopenharmony_ci for (int i = 0; i < n; i++) { 61cb93a386Sopenharmony_ci this->performTest(fDst, fSrc, kBuffer); 62cb93a386Sopenharmony_ci } 63cb93a386Sopenharmony_ci } 64cb93a386Sopenharmony_ci 65cb93a386Sopenharmony_ciprivate: 66cb93a386Sopenharmony_ci using INHERITED = Benchmark; 67cb93a386Sopenharmony_ci}; 68cb93a386Sopenharmony_ci 69cb93a386Sopenharmony_ciclass MathBenchU32 : public MathBench { 70cb93a386Sopenharmony_cipublic: 71cb93a386Sopenharmony_ci MathBenchU32(const char name[]) : INHERITED(name) {} 72cb93a386Sopenharmony_ci 73cb93a386Sopenharmony_ciprotected: 74cb93a386Sopenharmony_ci virtual void performITest(uint32_t* SK_RESTRICT dst, 75cb93a386Sopenharmony_ci const uint32_t* SK_RESTRICT src, 76cb93a386Sopenharmony_ci int count) = 0; 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_ci void performTest(float* SK_RESTRICT dst, const float* SK_RESTRICT src, int count) override { 79cb93a386Sopenharmony_ci uint32_t* d = reinterpret_cast<uint32_t*>(dst); 80cb93a386Sopenharmony_ci const uint32_t* s = reinterpret_cast<const uint32_t*>(src); 81cb93a386Sopenharmony_ci this->performITest(d, s, count); 82cb93a386Sopenharmony_ci } 83cb93a386Sopenharmony_ciprivate: 84cb93a386Sopenharmony_ci using INHERITED = MathBench; 85cb93a386Sopenharmony_ci}; 86cb93a386Sopenharmony_ci 87cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 88cb93a386Sopenharmony_ci 89cb93a386Sopenharmony_ciclass NoOpMathBench : public MathBench { 90cb93a386Sopenharmony_cipublic: 91cb93a386Sopenharmony_ci NoOpMathBench() : INHERITED("noOp") {} 92cb93a386Sopenharmony_ciprotected: 93cb93a386Sopenharmony_ci void performTest(float* SK_RESTRICT dst, const float* SK_RESTRICT src, int count) override { 94cb93a386Sopenharmony_ci for (int i = 0; i < count; ++i) { 95cb93a386Sopenharmony_ci dst[i] = src[i] + 1; 96cb93a386Sopenharmony_ci } 97cb93a386Sopenharmony_ci } 98cb93a386Sopenharmony_ciprivate: 99cb93a386Sopenharmony_ci using INHERITED = MathBench; 100cb93a386Sopenharmony_ci}; 101cb93a386Sopenharmony_ci 102cb93a386Sopenharmony_ciclass SkRSqrtMathBench : public MathBench { 103cb93a386Sopenharmony_cipublic: 104cb93a386Sopenharmony_ci SkRSqrtMathBench() : INHERITED("sk_float_rsqrt") {} 105cb93a386Sopenharmony_ciprotected: 106cb93a386Sopenharmony_ci void performTest(float* SK_RESTRICT dst, const float* SK_RESTRICT src, int count) override { 107cb93a386Sopenharmony_ci for (int i = 0; i < count; ++i) { 108cb93a386Sopenharmony_ci dst[i] = sk_float_rsqrt(src[i]); 109cb93a386Sopenharmony_ci } 110cb93a386Sopenharmony_ci } 111cb93a386Sopenharmony_ciprivate: 112cb93a386Sopenharmony_ci using INHERITED = MathBench; 113cb93a386Sopenharmony_ci}; 114cb93a386Sopenharmony_ci 115cb93a386Sopenharmony_ci 116cb93a386Sopenharmony_ciclass SlowISqrtMathBench : public MathBench { 117cb93a386Sopenharmony_cipublic: 118cb93a386Sopenharmony_ci SlowISqrtMathBench() : INHERITED("slowIsqrt") {} 119cb93a386Sopenharmony_ciprotected: 120cb93a386Sopenharmony_ci void performTest(float* SK_RESTRICT dst, const float* SK_RESTRICT src, int count) override { 121cb93a386Sopenharmony_ci for (int i = 0; i < count; ++i) { 122cb93a386Sopenharmony_ci dst[i] = 1.0f / sk_float_sqrt(src[i]); 123cb93a386Sopenharmony_ci } 124cb93a386Sopenharmony_ci } 125cb93a386Sopenharmony_ciprivate: 126cb93a386Sopenharmony_ci using INHERITED = MathBench; 127cb93a386Sopenharmony_ci}; 128cb93a386Sopenharmony_ci 129cb93a386Sopenharmony_ciclass FastISqrtMathBench : public MathBench { 130cb93a386Sopenharmony_cipublic: 131cb93a386Sopenharmony_ci FastISqrtMathBench() : INHERITED("fastIsqrt") {} 132cb93a386Sopenharmony_ciprotected: 133cb93a386Sopenharmony_ci void performTest(float* SK_RESTRICT dst, const float* SK_RESTRICT src, int count) override { 134cb93a386Sopenharmony_ci for (int i = 0; i < count; ++i) { 135cb93a386Sopenharmony_ci dst[i] = sk_float_rsqrt(src[i]); 136cb93a386Sopenharmony_ci } 137cb93a386Sopenharmony_ci } 138cb93a386Sopenharmony_ciprivate: 139cb93a386Sopenharmony_ci using INHERITED = MathBench; 140cb93a386Sopenharmony_ci}; 141cb93a386Sopenharmony_ci 142cb93a386Sopenharmony_cistatic inline uint32_t QMul64(uint32_t value, U8CPU alpha) { 143cb93a386Sopenharmony_ci SkASSERT((uint8_t)alpha == alpha); 144cb93a386Sopenharmony_ci const uint32_t mask = 0xFF00FF; 145cb93a386Sopenharmony_ci 146cb93a386Sopenharmony_ci uint64_t tmp = value; 147cb93a386Sopenharmony_ci tmp = (tmp & mask) | ((tmp & ~mask) << 24); 148cb93a386Sopenharmony_ci tmp *= alpha; 149cb93a386Sopenharmony_ci return (uint32_t) (((tmp >> 8) & mask) | ((tmp >> 32) & ~mask)); 150cb93a386Sopenharmony_ci} 151cb93a386Sopenharmony_ci 152cb93a386Sopenharmony_ciclass QMul64Bench : public MathBenchU32 { 153cb93a386Sopenharmony_cipublic: 154cb93a386Sopenharmony_ci QMul64Bench() : INHERITED("qmul64") {} 155cb93a386Sopenharmony_ciprotected: 156cb93a386Sopenharmony_ci void performITest(uint32_t* SK_RESTRICT dst, 157cb93a386Sopenharmony_ci const uint32_t* SK_RESTRICT src, 158cb93a386Sopenharmony_ci int count) override { 159cb93a386Sopenharmony_ci for (int i = 0; i < count; ++i) { 160cb93a386Sopenharmony_ci dst[i] = QMul64(src[i], (uint8_t)i); 161cb93a386Sopenharmony_ci } 162cb93a386Sopenharmony_ci } 163cb93a386Sopenharmony_ciprivate: 164cb93a386Sopenharmony_ci using INHERITED = MathBenchU32; 165cb93a386Sopenharmony_ci}; 166cb93a386Sopenharmony_ci 167cb93a386Sopenharmony_ciclass QMul32Bench : public MathBenchU32 { 168cb93a386Sopenharmony_cipublic: 169cb93a386Sopenharmony_ci QMul32Bench() : INHERITED("qmul32") {} 170cb93a386Sopenharmony_ciprotected: 171cb93a386Sopenharmony_ci void performITest(uint32_t* SK_RESTRICT dst, 172cb93a386Sopenharmony_ci const uint32_t* SK_RESTRICT src, 173cb93a386Sopenharmony_ci int count) override { 174cb93a386Sopenharmony_ci for (int i = 0; i < count; ++i) { 175cb93a386Sopenharmony_ci dst[i] = SkAlphaMulQ(src[i], (uint8_t)i); 176cb93a386Sopenharmony_ci } 177cb93a386Sopenharmony_ci } 178cb93a386Sopenharmony_ciprivate: 179cb93a386Sopenharmony_ci using INHERITED = MathBenchU32; 180cb93a386Sopenharmony_ci}; 181cb93a386Sopenharmony_ci 182cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 183cb93a386Sopenharmony_ci 184cb93a386Sopenharmony_cistatic bool isFinite_int(float x) { 185cb93a386Sopenharmony_ci uint32_t bits = SkFloat2Bits(x); // need unsigned for our shifts 186cb93a386Sopenharmony_ci int exponent = bits << 1 >> 24; 187cb93a386Sopenharmony_ci return exponent != 0xFF; 188cb93a386Sopenharmony_ci} 189cb93a386Sopenharmony_ci 190cb93a386Sopenharmony_cistatic bool isFinite_float(float x) { 191cb93a386Sopenharmony_ci return SkToBool(sk_float_isfinite(x)); 192cb93a386Sopenharmony_ci} 193cb93a386Sopenharmony_ci 194cb93a386Sopenharmony_cistatic bool isFinite_mulzero(float x) { 195cb93a386Sopenharmony_ci float y = x * 0; 196cb93a386Sopenharmony_ci return y == y; 197cb93a386Sopenharmony_ci} 198cb93a386Sopenharmony_ci 199cb93a386Sopenharmony_cistatic bool isfinite_and_int(const float data[4]) { 200cb93a386Sopenharmony_ci return isFinite_int(data[0]) && isFinite_int(data[1]) && isFinite_int(data[2]) && isFinite_int(data[3]); 201cb93a386Sopenharmony_ci} 202cb93a386Sopenharmony_ci 203cb93a386Sopenharmony_cistatic bool isfinite_and_float(const float data[4]) { 204cb93a386Sopenharmony_ci return isFinite_float(data[0]) && isFinite_float(data[1]) && isFinite_float(data[2]) && isFinite_float(data[3]); 205cb93a386Sopenharmony_ci} 206cb93a386Sopenharmony_ci 207cb93a386Sopenharmony_cistatic bool isfinite_and_mulzero(const float data[4]) { 208cb93a386Sopenharmony_ci return isFinite_mulzero(data[0]) && isFinite_mulzero(data[1]) && isFinite_mulzero(data[2]) && isFinite_mulzero(data[3]); 209cb93a386Sopenharmony_ci} 210cb93a386Sopenharmony_ci 211cb93a386Sopenharmony_ci#define mulzeroadd(data) (data[0]*0 + data[1]*0 + data[2]*0 + data[3]*0) 212cb93a386Sopenharmony_ci 213cb93a386Sopenharmony_cistatic bool isfinite_plus_int(const float data[4]) { 214cb93a386Sopenharmony_ci return isFinite_int(mulzeroadd(data)); 215cb93a386Sopenharmony_ci} 216cb93a386Sopenharmony_ci 217cb93a386Sopenharmony_cistatic bool isfinite_plus_float(const float data[4]) { 218cb93a386Sopenharmony_ci return !sk_float_isnan(mulzeroadd(data)); 219cb93a386Sopenharmony_ci} 220cb93a386Sopenharmony_ci 221cb93a386Sopenharmony_cistatic bool isfinite_plus_mulzero(const float data[4]) { 222cb93a386Sopenharmony_ci float x = mulzeroadd(data); 223cb93a386Sopenharmony_ci return x == x; 224cb93a386Sopenharmony_ci} 225cb93a386Sopenharmony_ci 226cb93a386Sopenharmony_citypedef bool (*IsFiniteProc)(const float[]); 227cb93a386Sopenharmony_ci 228cb93a386Sopenharmony_ci#define MAKEREC(name) { name, #name } 229cb93a386Sopenharmony_ci 230cb93a386Sopenharmony_cistatic const struct { 231cb93a386Sopenharmony_ci IsFiniteProc fProc; 232cb93a386Sopenharmony_ci const char* fName; 233cb93a386Sopenharmony_ci} gRec[] = { 234cb93a386Sopenharmony_ci MAKEREC(isfinite_and_int), 235cb93a386Sopenharmony_ci MAKEREC(isfinite_and_float), 236cb93a386Sopenharmony_ci MAKEREC(isfinite_and_mulzero), 237cb93a386Sopenharmony_ci MAKEREC(isfinite_plus_int), 238cb93a386Sopenharmony_ci MAKEREC(isfinite_plus_float), 239cb93a386Sopenharmony_ci MAKEREC(isfinite_plus_mulzero), 240cb93a386Sopenharmony_ci}; 241cb93a386Sopenharmony_ci 242cb93a386Sopenharmony_ci#undef MAKEREC 243cb93a386Sopenharmony_ci 244cb93a386Sopenharmony_cistatic bool isFinite(const SkRect& r) { 245cb93a386Sopenharmony_ci // x * 0 will be NaN iff x is infinity or NaN. 246cb93a386Sopenharmony_ci // a + b will be NaN iff either a or b is NaN. 247cb93a386Sopenharmony_ci float value = r.fLeft * 0 + r.fTop * 0 + r.fRight * 0 + r.fBottom * 0; 248cb93a386Sopenharmony_ci 249cb93a386Sopenharmony_ci // value is either NaN or it is finite (zero). 250cb93a386Sopenharmony_ci // value==value will be true iff value is not NaN 251cb93a386Sopenharmony_ci return value == value; 252cb93a386Sopenharmony_ci} 253cb93a386Sopenharmony_ci 254cb93a386Sopenharmony_ciclass IsFiniteBench : public Benchmark { 255cb93a386Sopenharmony_ci enum { 256cb93a386Sopenharmony_ci N = 1000, 257cb93a386Sopenharmony_ci }; 258cb93a386Sopenharmony_ci float fData[N]; 259cb93a386Sopenharmony_cipublic: 260cb93a386Sopenharmony_ci 261cb93a386Sopenharmony_ci IsFiniteBench(int index) { 262cb93a386Sopenharmony_ci SkRandom rand; 263cb93a386Sopenharmony_ci 264cb93a386Sopenharmony_ci for (int i = 0; i < N; ++i) { 265cb93a386Sopenharmony_ci fData[i] = rand.nextSScalar1(); 266cb93a386Sopenharmony_ci } 267cb93a386Sopenharmony_ci 268cb93a386Sopenharmony_ci if (index < 0) { 269cb93a386Sopenharmony_ci fProc = nullptr; 270cb93a386Sopenharmony_ci fName = "isfinite_rect"; 271cb93a386Sopenharmony_ci } else { 272cb93a386Sopenharmony_ci fProc = gRec[index].fProc; 273cb93a386Sopenharmony_ci fName = gRec[index].fName; 274cb93a386Sopenharmony_ci } 275cb93a386Sopenharmony_ci } 276cb93a386Sopenharmony_ci 277cb93a386Sopenharmony_ci bool isSuitableFor(Backend backend) override { 278cb93a386Sopenharmony_ci return backend == kNonRendering_Backend; 279cb93a386Sopenharmony_ci } 280cb93a386Sopenharmony_ci 281cb93a386Sopenharmony_ciprotected: 282cb93a386Sopenharmony_ci void onDraw(int loops, SkCanvas*) override { 283cb93a386Sopenharmony_ci IsFiniteProc proc = fProc; 284cb93a386Sopenharmony_ci const float* data = fData; 285cb93a386Sopenharmony_ci // do this so the compiler won't throw away the function call 286cb93a386Sopenharmony_ci int counter = 0; 287cb93a386Sopenharmony_ci 288cb93a386Sopenharmony_ci if (proc) { 289cb93a386Sopenharmony_ci for (int j = 0; j < loops; ++j) { 290cb93a386Sopenharmony_ci for (int i = 0; i < N - 4; ++i) { 291cb93a386Sopenharmony_ci counter += proc(&data[i]); 292cb93a386Sopenharmony_ci } 293cb93a386Sopenharmony_ci } 294cb93a386Sopenharmony_ci } else { 295cb93a386Sopenharmony_ci for (int j = 0; j < loops; ++j) { 296cb93a386Sopenharmony_ci for (int i = 0; i < N - 4; ++i) { 297cb93a386Sopenharmony_ci const SkRect* r = reinterpret_cast<const SkRect*>(&data[i]); 298cb93a386Sopenharmony_ci if (false) { // avoid bit rot, suppress warning 299cb93a386Sopenharmony_ci isFinite(*r); 300cb93a386Sopenharmony_ci } 301cb93a386Sopenharmony_ci counter += r->isFinite(); 302cb93a386Sopenharmony_ci } 303cb93a386Sopenharmony_ci } 304cb93a386Sopenharmony_ci } 305cb93a386Sopenharmony_ci 306cb93a386Sopenharmony_ci SkPaint paint; 307cb93a386Sopenharmony_ci if (paint.getAlpha() == 0) { 308cb93a386Sopenharmony_ci SkDebugf("%d\n", counter); 309cb93a386Sopenharmony_ci } 310cb93a386Sopenharmony_ci } 311cb93a386Sopenharmony_ci 312cb93a386Sopenharmony_ci const char* onGetName() override { 313cb93a386Sopenharmony_ci return fName; 314cb93a386Sopenharmony_ci } 315cb93a386Sopenharmony_ci 316cb93a386Sopenharmony_ciprivate: 317cb93a386Sopenharmony_ci IsFiniteProc fProc; 318cb93a386Sopenharmony_ci const char* fName; 319cb93a386Sopenharmony_ci 320cb93a386Sopenharmony_ci using INHERITED = Benchmark; 321cb93a386Sopenharmony_ci}; 322cb93a386Sopenharmony_ci 323cb93a386Sopenharmony_ciclass FloorBench : public Benchmark { 324cb93a386Sopenharmony_ci enum { 325cb93a386Sopenharmony_ci ARRAY = 1000, 326cb93a386Sopenharmony_ci }; 327cb93a386Sopenharmony_ci float fData[ARRAY]; 328cb93a386Sopenharmony_ci bool fFast; 329cb93a386Sopenharmony_cipublic: 330cb93a386Sopenharmony_ci 331cb93a386Sopenharmony_ci FloorBench(bool fast) : fFast(fast) { 332cb93a386Sopenharmony_ci SkRandom rand; 333cb93a386Sopenharmony_ci 334cb93a386Sopenharmony_ci for (int i = 0; i < ARRAY; ++i) { 335cb93a386Sopenharmony_ci fData[i] = rand.nextSScalar1(); 336cb93a386Sopenharmony_ci } 337cb93a386Sopenharmony_ci 338cb93a386Sopenharmony_ci if (fast) { 339cb93a386Sopenharmony_ci fName = "floor_fast"; 340cb93a386Sopenharmony_ci } else { 341cb93a386Sopenharmony_ci fName = "floor_std"; 342cb93a386Sopenharmony_ci } 343cb93a386Sopenharmony_ci } 344cb93a386Sopenharmony_ci 345cb93a386Sopenharmony_ci bool isSuitableFor(Backend backend) override { 346cb93a386Sopenharmony_ci return backend == kNonRendering_Backend; 347cb93a386Sopenharmony_ci } 348cb93a386Sopenharmony_ci 349cb93a386Sopenharmony_ci virtual void process(float) {} 350cb93a386Sopenharmony_ci 351cb93a386Sopenharmony_ciprotected: 352cb93a386Sopenharmony_ci void onDraw(int loops, SkCanvas*) override { 353cb93a386Sopenharmony_ci SkRandom rand; 354cb93a386Sopenharmony_ci float accum = 0; 355cb93a386Sopenharmony_ci const float* data = fData; 356cb93a386Sopenharmony_ci 357cb93a386Sopenharmony_ci if (fFast) { 358cb93a386Sopenharmony_ci for (int j = 0; j < loops; ++j) { 359cb93a386Sopenharmony_ci for (int i = 0; i < ARRAY; ++i) { 360cb93a386Sopenharmony_ci accum += fast_floor(data[i]); 361cb93a386Sopenharmony_ci } 362cb93a386Sopenharmony_ci this->process(accum); 363cb93a386Sopenharmony_ci } 364cb93a386Sopenharmony_ci } else { 365cb93a386Sopenharmony_ci for (int j = 0; j < loops; ++j) { 366cb93a386Sopenharmony_ci for (int i = 0; i < ARRAY; ++i) { 367cb93a386Sopenharmony_ci accum += sk_float_floor(data[i]); 368cb93a386Sopenharmony_ci } 369cb93a386Sopenharmony_ci this->process(accum); 370cb93a386Sopenharmony_ci } 371cb93a386Sopenharmony_ci } 372cb93a386Sopenharmony_ci } 373cb93a386Sopenharmony_ci 374cb93a386Sopenharmony_ci const char* onGetName() override { 375cb93a386Sopenharmony_ci return fName; 376cb93a386Sopenharmony_ci } 377cb93a386Sopenharmony_ci 378cb93a386Sopenharmony_ciprivate: 379cb93a386Sopenharmony_ci const char* fName; 380cb93a386Sopenharmony_ci 381cb93a386Sopenharmony_ci using INHERITED = Benchmark; 382cb93a386Sopenharmony_ci}; 383cb93a386Sopenharmony_ci 384cb93a386Sopenharmony_ciclass CLZBench : public Benchmark { 385cb93a386Sopenharmony_ci enum { 386cb93a386Sopenharmony_ci ARRAY = 1000, 387cb93a386Sopenharmony_ci }; 388cb93a386Sopenharmony_ci uint32_t fData[ARRAY]; 389cb93a386Sopenharmony_ci bool fUsePortable; 390cb93a386Sopenharmony_ci 391cb93a386Sopenharmony_cipublic: 392cb93a386Sopenharmony_ci CLZBench(bool usePortable) : fUsePortable(usePortable) { 393cb93a386Sopenharmony_ci 394cb93a386Sopenharmony_ci SkRandom rand; 395cb93a386Sopenharmony_ci for (int i = 0; i < ARRAY; ++i) { 396cb93a386Sopenharmony_ci fData[i] = rand.nextU(); 397cb93a386Sopenharmony_ci } 398cb93a386Sopenharmony_ci 399cb93a386Sopenharmony_ci if (fUsePortable) { 400cb93a386Sopenharmony_ci fName = "clz_portable"; 401cb93a386Sopenharmony_ci } else { 402cb93a386Sopenharmony_ci fName = "clz_intrinsic"; 403cb93a386Sopenharmony_ci } 404cb93a386Sopenharmony_ci } 405cb93a386Sopenharmony_ci 406cb93a386Sopenharmony_ci bool isSuitableFor(Backend backend) override { 407cb93a386Sopenharmony_ci return backend == kNonRendering_Backend; 408cb93a386Sopenharmony_ci } 409cb93a386Sopenharmony_ci 410cb93a386Sopenharmony_ci // just so the compiler doesn't remove our loops 411cb93a386Sopenharmony_ci virtual void process(int) {} 412cb93a386Sopenharmony_ci 413cb93a386Sopenharmony_ciprotected: 414cb93a386Sopenharmony_ci void onDraw(int loops, SkCanvas*) override { 415cb93a386Sopenharmony_ci int accum = 0; 416cb93a386Sopenharmony_ci 417cb93a386Sopenharmony_ci if (fUsePortable) { 418cb93a386Sopenharmony_ci for (int j = 0; j < loops; ++j) { 419cb93a386Sopenharmony_ci for (int i = 0; i < ARRAY; ++i) { 420cb93a386Sopenharmony_ci accum += SkCLZ_portable(fData[i]); 421cb93a386Sopenharmony_ci } 422cb93a386Sopenharmony_ci this->process(accum); 423cb93a386Sopenharmony_ci } 424cb93a386Sopenharmony_ci } else { 425cb93a386Sopenharmony_ci for (int j = 0; j < loops; ++j) { 426cb93a386Sopenharmony_ci for (int i = 0; i < ARRAY; ++i) { 427cb93a386Sopenharmony_ci accum += SkCLZ(fData[i]); 428cb93a386Sopenharmony_ci } 429cb93a386Sopenharmony_ci this->process(accum); 430cb93a386Sopenharmony_ci } 431cb93a386Sopenharmony_ci } 432cb93a386Sopenharmony_ci } 433cb93a386Sopenharmony_ci 434cb93a386Sopenharmony_ci const char* onGetName() override { 435cb93a386Sopenharmony_ci return fName; 436cb93a386Sopenharmony_ci } 437cb93a386Sopenharmony_ci 438cb93a386Sopenharmony_ciprivate: 439cb93a386Sopenharmony_ci const char* fName; 440cb93a386Sopenharmony_ci 441cb93a386Sopenharmony_ci using INHERITED = Benchmark; 442cb93a386Sopenharmony_ci}; 443cb93a386Sopenharmony_ci 444cb93a386Sopenharmony_ciclass CTZBench : public Benchmark { 445cb93a386Sopenharmony_ci enum { 446cb93a386Sopenharmony_ci ARRAY = 1000, 447cb93a386Sopenharmony_ci }; 448cb93a386Sopenharmony_ci uint32_t fData[ARRAY]; 449cb93a386Sopenharmony_ci bool fUsePortable; 450cb93a386Sopenharmony_ci 451cb93a386Sopenharmony_cipublic: 452cb93a386Sopenharmony_ci CTZBench(bool usePortable) : fUsePortable(usePortable) { 453cb93a386Sopenharmony_ci 454cb93a386Sopenharmony_ci SkRandom rand; 455cb93a386Sopenharmony_ci for (int i = 0; i < ARRAY; ++i) { 456cb93a386Sopenharmony_ci fData[i] = rand.nextU(); 457cb93a386Sopenharmony_ci } 458cb93a386Sopenharmony_ci 459cb93a386Sopenharmony_ci if (fUsePortable) { 460cb93a386Sopenharmony_ci fName = "ctz_portable"; 461cb93a386Sopenharmony_ci } else { 462cb93a386Sopenharmony_ci fName = "ctz_intrinsic"; 463cb93a386Sopenharmony_ci } 464cb93a386Sopenharmony_ci } 465cb93a386Sopenharmony_ci 466cb93a386Sopenharmony_ci bool isSuitableFor(Backend backend) override { 467cb93a386Sopenharmony_ci return backend == kNonRendering_Backend; 468cb93a386Sopenharmony_ci } 469cb93a386Sopenharmony_ci 470cb93a386Sopenharmony_ci // just so the compiler doesn't remove our loops 471cb93a386Sopenharmony_ci virtual void process(int) {} 472cb93a386Sopenharmony_ci 473cb93a386Sopenharmony_ciprotected: 474cb93a386Sopenharmony_ci void onDraw(int loops, SkCanvas*) override { 475cb93a386Sopenharmony_ci int accum = 0; 476cb93a386Sopenharmony_ci 477cb93a386Sopenharmony_ci if (fUsePortable) { 478cb93a386Sopenharmony_ci for (int j = 0; j < loops; ++j) { 479cb93a386Sopenharmony_ci for (int i = 0; i < ARRAY; ++i) { 480cb93a386Sopenharmony_ci accum += SkCTZ_portable(fData[i]); 481cb93a386Sopenharmony_ci } 482cb93a386Sopenharmony_ci this->process(accum); 483cb93a386Sopenharmony_ci } 484cb93a386Sopenharmony_ci } else { 485cb93a386Sopenharmony_ci for (int j = 0; j < loops; ++j) { 486cb93a386Sopenharmony_ci for (int i = 0; i < ARRAY; ++i) { 487cb93a386Sopenharmony_ci accum += SkCTZ(fData[i]); 488cb93a386Sopenharmony_ci } 489cb93a386Sopenharmony_ci this->process(accum); 490cb93a386Sopenharmony_ci } 491cb93a386Sopenharmony_ci } 492cb93a386Sopenharmony_ci } 493cb93a386Sopenharmony_ci 494cb93a386Sopenharmony_ci const char* onGetName() override { 495cb93a386Sopenharmony_ci return fName; 496cb93a386Sopenharmony_ci } 497cb93a386Sopenharmony_ci 498cb93a386Sopenharmony_ciprivate: 499cb93a386Sopenharmony_ci const char* fName; 500cb93a386Sopenharmony_ci 501cb93a386Sopenharmony_ci using INHERITED = Benchmark; 502cb93a386Sopenharmony_ci}; 503cb93a386Sopenharmony_ci 504cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 505cb93a386Sopenharmony_ci 506cb93a386Sopenharmony_ciclass NormalizeBench : public Benchmark { 507cb93a386Sopenharmony_ci enum { 508cb93a386Sopenharmony_ci ARRAY =1000, 509cb93a386Sopenharmony_ci }; 510cb93a386Sopenharmony_ci SkVector fVec[ARRAY]; 511cb93a386Sopenharmony_ci 512cb93a386Sopenharmony_cipublic: 513cb93a386Sopenharmony_ci NormalizeBench() { 514cb93a386Sopenharmony_ci SkRandom rand; 515cb93a386Sopenharmony_ci for (int i = 0; i < ARRAY; ++i) { 516cb93a386Sopenharmony_ci fVec[i].set(rand.nextSScalar1(), rand.nextSScalar1()); 517cb93a386Sopenharmony_ci } 518cb93a386Sopenharmony_ci 519cb93a386Sopenharmony_ci fName = "point_normalize"; 520cb93a386Sopenharmony_ci } 521cb93a386Sopenharmony_ci 522cb93a386Sopenharmony_ci bool isSuitableFor(Backend backend) override { 523cb93a386Sopenharmony_ci return backend == kNonRendering_Backend; 524cb93a386Sopenharmony_ci } 525cb93a386Sopenharmony_ci 526cb93a386Sopenharmony_ci // just so the compiler doesn't remove our loops 527cb93a386Sopenharmony_ci virtual void process(int) {} 528cb93a386Sopenharmony_ci 529cb93a386Sopenharmony_ciprotected: 530cb93a386Sopenharmony_ci void onDraw(int loops, SkCanvas*) override { 531cb93a386Sopenharmony_ci int accum = 0; 532cb93a386Sopenharmony_ci 533cb93a386Sopenharmony_ci for (int j = 0; j < loops; ++j) { 534cb93a386Sopenharmony_ci for (int i = 0; i < ARRAY; ++i) { 535cb93a386Sopenharmony_ci accum += fVec[i].normalize(); 536cb93a386Sopenharmony_ci } 537cb93a386Sopenharmony_ci this->process(accum); 538cb93a386Sopenharmony_ci } 539cb93a386Sopenharmony_ci } 540cb93a386Sopenharmony_ci 541cb93a386Sopenharmony_ci const char* onGetName() override { 542cb93a386Sopenharmony_ci return fName; 543cb93a386Sopenharmony_ci } 544cb93a386Sopenharmony_ci 545cb93a386Sopenharmony_ciprivate: 546cb93a386Sopenharmony_ci const char* fName; 547cb93a386Sopenharmony_ci 548cb93a386Sopenharmony_ci using INHERITED = Benchmark; 549cb93a386Sopenharmony_ci}; 550cb93a386Sopenharmony_ci 551cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 552cb93a386Sopenharmony_ci 553cb93a386Sopenharmony_ciclass FixedMathBench : public Benchmark { 554cb93a386Sopenharmony_ci enum { 555cb93a386Sopenharmony_ci N = 1000, 556cb93a386Sopenharmony_ci }; 557cb93a386Sopenharmony_ci float fData[N]; 558cb93a386Sopenharmony_ci SkFixed fResult[N]; 559cb93a386Sopenharmony_cipublic: 560cb93a386Sopenharmony_ci 561cb93a386Sopenharmony_ci FixedMathBench() { 562cb93a386Sopenharmony_ci SkRandom rand; 563cb93a386Sopenharmony_ci for (int i = 0; i < N; ++i) { 564cb93a386Sopenharmony_ci fData[i] = rand.nextSScalar1(); 565cb93a386Sopenharmony_ci } 566cb93a386Sopenharmony_ci 567cb93a386Sopenharmony_ci } 568cb93a386Sopenharmony_ci 569cb93a386Sopenharmony_ci bool isSuitableFor(Backend backend) override { 570cb93a386Sopenharmony_ci return backend == kNonRendering_Backend; 571cb93a386Sopenharmony_ci } 572cb93a386Sopenharmony_ci 573cb93a386Sopenharmony_ciprotected: 574cb93a386Sopenharmony_ci void onDraw(int loops, SkCanvas*) override { 575cb93a386Sopenharmony_ci for (int j = 0; j < loops; ++j) { 576cb93a386Sopenharmony_ci for (int i = 0; i < N - 4; ++i) { 577cb93a386Sopenharmony_ci fResult[i] = SkFloatToFixed(fData[i]); 578cb93a386Sopenharmony_ci } 579cb93a386Sopenharmony_ci } 580cb93a386Sopenharmony_ci 581cb93a386Sopenharmony_ci SkPaint paint; 582cb93a386Sopenharmony_ci if (paint.getAlpha() == 0) { 583cb93a386Sopenharmony_ci SkDebugf("%d\n", fResult[0]); 584cb93a386Sopenharmony_ci } 585cb93a386Sopenharmony_ci } 586cb93a386Sopenharmony_ci 587cb93a386Sopenharmony_ci const char* onGetName() override { 588cb93a386Sopenharmony_ci return "float_to_fixed"; 589cb93a386Sopenharmony_ci } 590cb93a386Sopenharmony_ci 591cb93a386Sopenharmony_ciprivate: 592cb93a386Sopenharmony_ci using INHERITED = Benchmark; 593cb93a386Sopenharmony_ci}; 594cb93a386Sopenharmony_ci 595cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 596cb93a386Sopenharmony_ci 597cb93a386Sopenharmony_citemplate <typename T> 598cb93a386Sopenharmony_ciclass DivModBench : public Benchmark { 599cb93a386Sopenharmony_ci SkString fName; 600cb93a386Sopenharmony_cipublic: 601cb93a386Sopenharmony_ci explicit DivModBench(const char* name) { 602cb93a386Sopenharmony_ci fName.printf("divmod_%s", name); 603cb93a386Sopenharmony_ci } 604cb93a386Sopenharmony_ci 605cb93a386Sopenharmony_ci bool isSuitableFor(Backend backend) override { 606cb93a386Sopenharmony_ci return backend == kNonRendering_Backend; 607cb93a386Sopenharmony_ci } 608cb93a386Sopenharmony_ci 609cb93a386Sopenharmony_ciprotected: 610cb93a386Sopenharmony_ci const char* onGetName() override { 611cb93a386Sopenharmony_ci return fName.c_str(); 612cb93a386Sopenharmony_ci } 613cb93a386Sopenharmony_ci 614cb93a386Sopenharmony_ci void onDraw(int loops, SkCanvas*) override { 615cb93a386Sopenharmony_ci volatile T a = 0, b = 0; 616cb93a386Sopenharmony_ci T div = 0, mod = 0; 617cb93a386Sopenharmony_ci for (int i = 0; i < loops; i++) { 618cb93a386Sopenharmony_ci if ((T)i == 0) continue; // Small T will wrap around. 619cb93a386Sopenharmony_ci SkTDivMod((T)(i+1), (T)i, &div, &mod); 620cb93a386Sopenharmony_ci a ^= div; 621cb93a386Sopenharmony_ci b ^= mod; 622cb93a386Sopenharmony_ci } 623cb93a386Sopenharmony_ci } 624cb93a386Sopenharmony_ci}; 625cb93a386Sopenharmony_ciDEF_BENCH(return new DivModBench<uint8_t>("uint8_t")) 626cb93a386Sopenharmony_ciDEF_BENCH(return new DivModBench<uint16_t>("uint16_t")) 627cb93a386Sopenharmony_ciDEF_BENCH(return new DivModBench<uint32_t>("uint32_t")) 628cb93a386Sopenharmony_ciDEF_BENCH(return new DivModBench<uint64_t>("uint64_t")) 629cb93a386Sopenharmony_ci 630cb93a386Sopenharmony_ciDEF_BENCH(return new DivModBench<int8_t>("int8_t")) 631cb93a386Sopenharmony_ciDEF_BENCH(return new DivModBench<int16_t>("int16_t")) 632cb93a386Sopenharmony_ciDEF_BENCH(return new DivModBench<int32_t>("int32_t")) 633cb93a386Sopenharmony_ciDEF_BENCH(return new DivModBench<int64_t>("int64_t")) 634cb93a386Sopenharmony_ci 635cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 636cb93a386Sopenharmony_ci 637cb93a386Sopenharmony_ciDEF_BENCH( return new NoOpMathBench(); ) 638cb93a386Sopenharmony_ciDEF_BENCH( return new SkRSqrtMathBench(); ) 639cb93a386Sopenharmony_ciDEF_BENCH( return new SlowISqrtMathBench(); ) 640cb93a386Sopenharmony_ciDEF_BENCH( return new FastISqrtMathBench(); ) 641cb93a386Sopenharmony_ciDEF_BENCH( return new QMul64Bench(); ) 642cb93a386Sopenharmony_ciDEF_BENCH( return new QMul32Bench(); ) 643cb93a386Sopenharmony_ci 644cb93a386Sopenharmony_ciDEF_BENCH( return new IsFiniteBench(-1); ) 645cb93a386Sopenharmony_ciDEF_BENCH( return new IsFiniteBench(0); ) 646cb93a386Sopenharmony_ciDEF_BENCH( return new IsFiniteBench(1); ) 647cb93a386Sopenharmony_ciDEF_BENCH( return new IsFiniteBench(2); ) 648cb93a386Sopenharmony_ciDEF_BENCH( return new IsFiniteBench(3); ) 649cb93a386Sopenharmony_ciDEF_BENCH( return new IsFiniteBench(4); ) 650cb93a386Sopenharmony_ciDEF_BENCH( return new IsFiniteBench(5); ) 651cb93a386Sopenharmony_ci 652cb93a386Sopenharmony_ciDEF_BENCH( return new FloorBench(false); ) 653cb93a386Sopenharmony_ciDEF_BENCH( return new FloorBench(true); ) 654cb93a386Sopenharmony_ci 655cb93a386Sopenharmony_ciDEF_BENCH( return new CLZBench(false); ) 656cb93a386Sopenharmony_ciDEF_BENCH( return new CLZBench(true); ) 657cb93a386Sopenharmony_ciDEF_BENCH( return new CTZBench(false); ) 658cb93a386Sopenharmony_ciDEF_BENCH( return new CTZBench(true); ) 659cb93a386Sopenharmony_ci 660cb93a386Sopenharmony_ciDEF_BENCH( return new NormalizeBench(); ) 661cb93a386Sopenharmony_ci 662cb93a386Sopenharmony_ciDEF_BENCH( return new FixedMathBench(); ) 663cb93a386Sopenharmony_ci 664cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////// 665cb93a386Sopenharmony_ci 666cb93a386Sopenharmony_ci#include "include/private/SkFloatBits.h" 667cb93a386Sopenharmony_ciclass Floor2IntBench : public Benchmark { 668cb93a386Sopenharmony_ci enum { 669cb93a386Sopenharmony_ci ARRAY = 1000, 670cb93a386Sopenharmony_ci }; 671cb93a386Sopenharmony_ci float fData[ARRAY]; 672cb93a386Sopenharmony_ci const bool fSat; 673cb93a386Sopenharmony_cipublic: 674cb93a386Sopenharmony_ci 675cb93a386Sopenharmony_ci Floor2IntBench(bool sat) : fSat(sat) { 676cb93a386Sopenharmony_ci SkRandom rand; 677cb93a386Sopenharmony_ci 678cb93a386Sopenharmony_ci for (int i = 0; i < ARRAY; ++i) { 679cb93a386Sopenharmony_ci fData[i] = SkBits2Float(rand.nextU()); 680cb93a386Sopenharmony_ci } 681cb93a386Sopenharmony_ci 682cb93a386Sopenharmony_ci if (sat) { 683cb93a386Sopenharmony_ci fName = "floor2int_sat"; 684cb93a386Sopenharmony_ci } else { 685cb93a386Sopenharmony_ci fName = "floor2int_undef"; 686cb93a386Sopenharmony_ci } 687cb93a386Sopenharmony_ci } 688cb93a386Sopenharmony_ci 689cb93a386Sopenharmony_ci bool isSuitableFor(Backend backend) override { 690cb93a386Sopenharmony_ci return backend == kNonRendering_Backend; 691cb93a386Sopenharmony_ci } 692cb93a386Sopenharmony_ci 693cb93a386Sopenharmony_ci // These exist to try to stop the compiler from detecting what we doing, and throwing 694cb93a386Sopenharmony_ci // parts away (or knowing exactly how big the loop counts are). 695cb93a386Sopenharmony_ci virtual void process(unsigned) {} 696cb93a386Sopenharmony_ci virtual int count() { return ARRAY; } 697cb93a386Sopenharmony_ci 698cb93a386Sopenharmony_ciprotected: 699cb93a386Sopenharmony_ci void onDraw(int loops, SkCanvas*) override { 700cb93a386Sopenharmony_ci // used unsigned to avoid undefined behavior if/when the += might overflow 701cb93a386Sopenharmony_ci unsigned accum = 0; 702cb93a386Sopenharmony_ci 703cb93a386Sopenharmony_ci for (int j = 0; j < loops; ++j) { 704cb93a386Sopenharmony_ci int n = this->count(); 705cb93a386Sopenharmony_ci if (fSat) { 706cb93a386Sopenharmony_ci for (int i = 0; i < n; ++i) { 707cb93a386Sopenharmony_ci accum += sk_float_floor2int(fData[i]); 708cb93a386Sopenharmony_ci } 709cb93a386Sopenharmony_ci } else { 710cb93a386Sopenharmony_ci for (int i = 0; i < n; ++i) { 711cb93a386Sopenharmony_ci accum += sk_float_floor2int_no_saturate(fData[i]); 712cb93a386Sopenharmony_ci } 713cb93a386Sopenharmony_ci } 714cb93a386Sopenharmony_ci this->process(accum); 715cb93a386Sopenharmony_ci } 716cb93a386Sopenharmony_ci } 717cb93a386Sopenharmony_ci 718cb93a386Sopenharmony_ci const char* onGetName() override { return fName; } 719cb93a386Sopenharmony_ci 720cb93a386Sopenharmony_ciprivate: 721cb93a386Sopenharmony_ci const char* fName; 722cb93a386Sopenharmony_ci 723cb93a386Sopenharmony_ci using INHERITED = Benchmark; 724cb93a386Sopenharmony_ci}; 725cb93a386Sopenharmony_ciDEF_BENCH( return new Floor2IntBench(false); ) 726cb93a386Sopenharmony_ciDEF_BENCH( return new Floor2IntBench(true); ) 727cb93a386Sopenharmony_ci 728