Coverage Report

Created: 2026-10-16 06:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/haproxy/include/import/slz-prv.h
Line
Count
Source
1
/*
2
 * Copyright (C) 2013-2015 Willy Tarreau <w@1wt.eu>
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining
5
 * a copy of this software and associated documentation files (the
6
 * "Software"), to deal in the Software without restriction, including
7
 * without limitation the rights to use, copy, modify, merge, publish,
8
 * distribute, sublicense, and/or sell copies of the Software, and to
9
 * permit persons to whom the Software is furnished to do so, subject to
10
 * the following conditions:
11
 *
12
 * The above copyright notice and this permission notice shall be
13
 * included in all copies or substantial portions of the Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
 * OTHER DEALINGS IN THE SOFTWARE.
23
 */
24
25
#ifndef _SLZ_PRV_H
26
#define _SLZ_PRV_H
27
28
/* We have two macros UNALIGNED_LE_OK and UNALIGNED_FASTER. The latter indicates
29
 * that using unaligned data is faster than a simple shift. On x86 32-bit at
30
 * least it is not the case as the per-byte access is 30% faster. A core2-duo on
31
 * x86_64 is 7% faster to read one byte + shifting by 8 than to read one word,
32
 * but a core i5 is 7% faster doing the unaligned read, so we privilege more
33
 * recent implementations here.
34
 */
35
#if defined(__x86_64__)
36
#define UNALIGNED_LE_OK
37
#define UNALIGNED_FASTER
38
#define HAVE_FAST_MULT
39
#elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)
40
#define UNALIGNED_LE_OK
41
//#define UNALIGNED_FASTER
42
#elif defined(__ARMEL__) && defined(__ARM_ARCH_7A__)
43
#define UNALIGNED_LE_OK
44
#define UNALIGNED_FASTER
45
#elif defined(__ARM_ARCH_8A) || defined(__ARM_FEATURE_UNALIGNED)
46
#define UNALIGNED_LE_OK
47
#define UNALIGNED_FASTER
48
#define HAVE_FAST_MULT
49
#endif
50
51
/* Log2 of the size of the hash table used for the references table. */
52
0
#define HASH_BITS 13
53
54
/* uses the most suitable crc32 function to update crc on <buf, len> */
55
static inline uint32_t update_crc(uint32_t crc, const void *buf, int len)
56
0
{
57
0
  return slz_crc32_by4(crc, buf, len);
58
0
}
Unexecuted instantiation: slz.c:update_crc
Unexecuted instantiation: slz_common.c:update_crc
Unexecuted instantiation: uslz.c:update_crc
59
60
/* This hash provides good average results on HTML contents, and is among the
61
 * few which provide almost optimal results on various different pages.
62
 */
63
static inline uint32_t slz_hash(uint32_t a)
64
0
{
65
#if defined(__ARM_FEATURE_CRC32)
66
#  if defined(__ARM_ARCH_ISA_A64)
67
  // 64 bit mode
68
  __asm__ volatile("crc32w %w0,%w0,%w1" : "+r"(a) : "r"(0));
69
#  else
70
  // 32 bit mode (e.g. armv7 compiler building for armv8
71
  __asm__ volatile("crc32w %0,%0,%1" : "+r"(a) : "r"(0));
72
#  endif
73
  return a >> (32 - HASH_BITS);
74
#elif defined(__SSE4_2__) && defined(USE_CRC32C_HASH)
75
  // SSE 4.2 offers CRC32C which is a bit slower than the multiply
76
  // but provides a slightly smoother hash
77
  __asm__ volatile("crc32l %1,%0" : "+r"(a) : "r"(0));
78
  return a >> (32 - HASH_BITS);
79
#elif defined(HAVE_FAST_MULT)
80
  // optimal factor for HASH_BITS=12 and HASH_BITS=13 among 48k tested: 0x1af42f
81
0
  return (a * 0x1af42f) >> (32 - HASH_BITS);
82
#else
83
  return ((a << 19) + (a << 6) - a) >> (32 - HASH_BITS);
84
#endif
85
0
}
Unexecuted instantiation: slz.c:slz_hash
Unexecuted instantiation: slz_common.c:slz_hash
Unexecuted instantiation: uslz.c:slz_hash
86
87
/* This function compares buffers <a> and <b> and reads 32 or 64 bits at a time
88
 * during the approach. It makes us of unaligned little endian memory accesses
89
 * on capable architectures. <max> is the maximum number of bytes that can be
90
 * read, so both <a> and <b> must have at least <max> bytes ahead. <max> may
91
 * safely be null or negative if that simplifies computations in the caller.
92
 */
93
static inline long memmatch(const unsigned char *a, const unsigned char *b, long max)
94
0
{
95
0
  long len = 0;
96
97
0
#ifdef UNALIGNED_LE_OK
98
0
  unsigned long xor;
99
100
0
  while (1) {
101
0
    if ((long)(len + 2 * sizeof(long)) > max) {
102
0
      while (len < max) {
103
0
        if (a[len] != b[len])
104
0
          break;
105
0
        len++;
106
0
      }
107
0
      return len;
108
0
    }
109
110
0
    xor = *(long *)&a[len] ^ *(long *)&b[len];
111
0
    if (xor)
112
0
      break;
113
0
    len += sizeof(long);
114
115
0
    xor = *(long *)&a[len] ^ *(long *)&b[len];
116
0
    if (xor)
117
0
      break;
118
0
    len += sizeof(long);
119
0
  }
120
121
0
#if defined(__x86_64__) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)
122
  /* x86 has bsf. We know that xor is non-null here */
123
0
  asm("bsf %1,%0\n" : "=r"(xor) : "0" (xor));
124
0
  return len + xor / 8;
125
#else
126
  if (sizeof(long) > 4 && !(xor & 0xffffffff)) {
127
    /* This code is optimized out on 32-bit archs, but we still
128
     * need to shift in two passes to avoid a warning. It is
129
     * properly optimized out as a single shift.
130
     */
131
    xor >>= 16; xor >>= 16;
132
    if (xor & 0xffff) {
133
      if (xor & 0xff)
134
        return len + 4;
135
      return len + 5;
136
    }
137
    if (xor & 0xffffff)
138
      return len + 6;
139
    return len + 7;
140
  }
141
142
  if (xor & 0xffff) {
143
    if (xor & 0xff)
144
      return len;
145
    return len + 1;
146
  }
147
  if (xor & 0xffffff)
148
    return len + 2;
149
  return len + 3;
150
#endif // x86
151
152
#else // UNALIGNED_LE_OK
153
  /* This is the generic version for big endian or unaligned-incompatible
154
   * architectures.
155
   */
156
  while (len < max) {
157
    if (a[len] != b[len])
158
      break;
159
    len++;
160
  }
161
  return len;
162
163
#endif
164
0
}
Unexecuted instantiation: slz.c:memmatch
Unexecuted instantiation: slz_common.c:memmatch
Unexecuted instantiation: uslz.c:memmatch
165
166
/* helper function to reverse bits in <input> which is expected to be
167
 * <len> bits long.
168
 */
169
static inline short rev_short(short input, int len)
170
8.19k
{
171
8.19k
  short ret = 0;
172
173
73.9k
  while (len) {
174
65.7k
    ret <<= 1;
175
65.7k
    ret |= (input & 1);
176
65.7k
    input >>= 1;
177
65.7k
    len--;
178
65.7k
  }
179
180
8.19k
  return ret;
181
8.19k
}
Unexecuted instantiation: slz.c:rev_short
Unexecuted instantiation: slz_common.c:rev_short
uslz.c:rev_short
Line
Count
Source
170
8.19k
{
171
8.19k
  short ret = 0;
172
173
73.9k
  while (len) {
174
65.7k
    ret <<= 1;
175
65.7k
    ret |= (input & 1);
176
65.7k
    input >>= 1;
177
65.7k
    len--;
178
65.7k
  }
179
180
8.19k
  return ret;
181
8.19k
}
182
183
#endif