2022-05-20 06:17:59 +08:00
|
|
|
/* Test dl-hash functions.
|
|
|
|
Copyright (C) 2022 Free Software Foundation, Inc.
|
|
|
|
This file is part of the GNU C Library.
|
|
|
|
|
|
|
|
The GNU C Library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Lesser General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
The GNU C Library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Lesser General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
|
|
License along with the GNU C Library; if not, see
|
|
|
|
<https://www.gnu.org/licenses/>. */
|
|
|
|
|
|
|
|
|
|
|
|
#include <simple-dl-hash.h>
|
elf: Optimize _dl_new_hash in dl-new-hash.h
Unroll slightly and enforce good instruction scheduling. This improves
performance on out-of-order machines. The unrolling allows for
pipelined multiplies.
As well, as an optional sysdep, reorder the operations and prevent
reassosiation for better scheduling and higher ILP. This commit
only adds the barrier for x86, although it should be either no
change or a win for any architecture.
Unrolling further started to induce slowdowns for sizes [0, 4]
but can help the loop so if larger sizes are the target further
unrolling can be beneficial.
Results for _dl_new_hash
Benchmarked on Tigerlake: 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz
Time as Geometric Mean of N=30 runs
Geometric of all benchmark New / Old: 0.674
type, length, New Time, Old Time, New Time / Old Time
fixed, 0, 2.865, 2.72, 1.053
fixed, 1, 3.567, 2.489, 1.433
fixed, 2, 2.577, 3.649, 0.706
fixed, 3, 3.644, 5.983, 0.609
fixed, 4, 4.211, 6.833, 0.616
fixed, 5, 4.741, 9.372, 0.506
fixed, 6, 5.415, 9.561, 0.566
fixed, 7, 6.649, 10.789, 0.616
fixed, 8, 8.081, 11.808, 0.684
fixed, 9, 8.427, 12.935, 0.651
fixed, 10, 8.673, 14.134, 0.614
fixed, 11, 10.69, 15.408, 0.694
fixed, 12, 10.789, 16.982, 0.635
fixed, 13, 12.169, 18.411, 0.661
fixed, 14, 12.659, 19.914, 0.636
fixed, 15, 13.526, 21.541, 0.628
fixed, 16, 14.211, 23.088, 0.616
fixed, 32, 29.412, 52.722, 0.558
fixed, 64, 65.41, 142.351, 0.459
fixed, 128, 138.505, 295.625, 0.469
fixed, 256, 291.707, 601.983, 0.485
random, 2, 12.698, 12.849, 0.988
random, 4, 16.065, 15.857, 1.013
random, 8, 19.564, 21.105, 0.927
random, 16, 23.919, 26.823, 0.892
random, 32, 31.987, 39.591, 0.808
random, 64, 49.282, 71.487, 0.689
random, 128, 82.23, 145.364, 0.566
random, 256, 152.209, 298.434, 0.51
Co-authored-by: Alexander Monakov <amonakov@ispras.ru>
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
2022-05-20 06:18:03 +08:00
|
|
|
#include <simple-dl-new-hash.h>
|
2022-05-20 06:17:59 +08:00
|
|
|
#include <dl-hash.h>
|
|
|
|
#include <dl-new-hash.h>
|
|
|
|
#include <support/support.h>
|
|
|
|
#include <support/check.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
typedef unsigned int (*hash_f) (const char *);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
do_fill_test (size_t len, int fill, const char *name, hash_f testf,
|
|
|
|
hash_f expecf)
|
|
|
|
{
|
|
|
|
uint32_t expec, res;
|
|
|
|
char buf[len + 1];
|
|
|
|
memset (buf, fill, len);
|
|
|
|
buf[len] = '\0';
|
|
|
|
|
|
|
|
expec = expecf (buf);
|
|
|
|
res = testf (buf);
|
|
|
|
if (expec != res)
|
|
|
|
FAIL_EXIT1 ("FAIL: fill(%d) %s(%zu), %x != %x\n", fill, name, len, expec,
|
|
|
|
res);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
do_fill_tests (size_t len, int fill)
|
|
|
|
{
|
|
|
|
if (do_fill_test (len, fill, "dl_new_hash", &_dl_new_hash,
|
|
|
|
&__simple_dl_new_hash))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return do_fill_test (len, fill, "dl_elf_hash", &_dl_elf_hash,
|
|
|
|
&__simple_dl_elf_hash);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
do_rand_test (size_t len, const char *name, hash_f testf, hash_f expecf)
|
|
|
|
{
|
|
|
|
uint32_t expec, res;
|
|
|
|
size_t i;
|
|
|
|
char buf[len + 1];
|
|
|
|
char v;
|
|
|
|
for (i = 0; i < len; ++i)
|
|
|
|
{
|
|
|
|
v = random ();
|
|
|
|
if (v == 0)
|
|
|
|
v = 1;
|
|
|
|
|
|
|
|
buf[i] = v;
|
|
|
|
}
|
|
|
|
buf[len] = '\0';
|
|
|
|
|
|
|
|
expec = expecf (buf);
|
|
|
|
res = testf (buf);
|
|
|
|
if (expec != res)
|
|
|
|
FAIL_EXIT1 ("FAIL: random %s(%zu), %x != %x\n", name, len, expec, res);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
do_rand_tests (size_t len)
|
|
|
|
{
|
|
|
|
if (do_rand_test (len, "dl_new_hash", &_dl_new_hash, &__simple_dl_new_hash))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return do_rand_test (len, "dl_elf_hash", &_dl_elf_hash, &__simple_dl_elf_hash);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
do_test (void)
|
|
|
|
{
|
|
|
|
size_t i, j;
|
|
|
|
for (i = 0; i < 100; ++i)
|
|
|
|
{
|
|
|
|
for (j = 0; j < 8192; ++j)
|
|
|
|
{
|
|
|
|
if (do_rand_tests (i))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if (do_fill_tests (i, -1) || do_fill_tests (i, 1)
|
|
|
|
|| do_fill_tests (i, 0x80) || do_fill_tests (i, 0x88))
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include <support/test-driver.c>
|