insert_string.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /* insert_string.h
  2. *
  3. * Copyright 2019 The Chromium Authors. All rights reserved.
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the Chromium source repository LICENSE file.
  6. */
  7. #if defined(_MSC_VER)
  8. #define INLINE __inline
  9. #else
  10. #define INLINE inline
  11. #endif
  12. #include "cpu_features.h"
  13. // clang-format off
  14. #if defined(CRC32_SIMD_SSE42_PCLMUL)
  15. #include <smmintrin.h> /* Required to make MSVC bot build pass. */
  16. #if defined(__clang__) || defined(__GNUC__)
  17. #define TARGET_CPU_WITH_CRC __attribute__((target("sse4.2")))
  18. #else
  19. #define TARGET_CPU_WITH_CRC
  20. #endif
  21. #define _cpu_crc32_u32 _mm_crc32_u32
  22. #elif defined(CRC32_ARMV8_CRC32)
  23. #if defined(__clang__)
  24. #define __crc32cw __builtin_arm_crc32cw
  25. #elif defined(__GNUC__)
  26. #define __crc32cw __builtin_aarch64_crc32cw
  27. #endif
  28. #if defined(__aarch64__) && defined(__clang__)
  29. #define TARGET_CPU_WITH_CRC __attribute__((target("crc")))
  30. #elif defined(__aarch64__) && defined(__GNUC__)
  31. #define TARGET_CPU_WITH_CRC __attribute__((target("+crc")))
  32. #elif defined(__clang__) // !defined(__aarch64__)
  33. #define TARGET_CPU_WITH_CRC __attribute__((target("armv8-a,crc")))
  34. #endif // defined(__aarch64__)
  35. #define _cpu_crc32_u32 __crc32cw
  36. #endif
  37. // clang-format on
  38. #if defined(TARGET_CPU_WITH_CRC)
  39. TARGET_CPU_WITH_CRC
  40. local INLINE Pos insert_string_simd(deflate_state* const s, const Pos str) {
  41. Pos ret;
  42. unsigned *ip, val, h = 0;
  43. ip = (unsigned*)&s->window[str];
  44. val = *ip;
  45. if (s->level >= 6)
  46. val &= 0xFFFFFF;
  47. /* Unlike the case of data integrity checks for GZIP format where the
  48. * polynomial used is defined (https://tools.ietf.org/html/rfc1952#page-11),
  49. * here it is just a hash function for the hash table used while
  50. * performing compression.
  51. */
  52. h = _cpu_crc32_u32(h, val);
  53. ret = s->head[h & s->hash_mask];
  54. s->head[h & s->hash_mask] = str;
  55. s->prev[str & s->w_mask] = ret;
  56. return ret;
  57. }
  58. #endif // TARGET_CPU_WITH_CRC
  59. /* ===========================================================================
  60. * Update a hash value with the given input byte
  61. * IN assertion: all calls to UPDATE_HASH are made with consecutive input
  62. * characters, so that a running hash key can be computed from the previous
  63. * key instead of complete recalculation each time.
  64. */
  65. #define UPDATE_HASH(s, h, c) (h = (((h) << s->hash_shift) ^ (c)) & s->hash_mask)
  66. /* ===========================================================================
  67. * Insert string str in the dictionary and set match_head to the previous head
  68. * of the hash chain (the most recent string with same hash key). Return
  69. * the previous length of the hash chain.
  70. * If this file is compiled with -DFASTEST, the compression level is forced
  71. * to 1, and no hash chains are maintained.
  72. * IN assertion: all calls to INSERT_STRING are made with consecutive input
  73. * characters and the first MIN_MATCH bytes of str are valid (except for
  74. * the last MIN_MATCH-1 bytes of the input file).
  75. */
  76. local INLINE Pos insert_string_c(deflate_state* const s, const Pos str) {
  77. Pos ret;
  78. UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH - 1)]);
  79. #ifdef FASTEST
  80. ret = s->head[s->ins_h];
  81. #else
  82. ret = s->prev[str & s->w_mask] = s->head[s->ins_h];
  83. #endif
  84. s->head[s->ins_h] = str;
  85. return ret;
  86. }
  87. local INLINE Pos insert_string(deflate_state* const s, const Pos str) {
  88. /* insert_string_simd string dictionary insertion: this SIMD symbol hashing
  89. * significantly improves data compression speed.
  90. *
  91. * Note: the generated compressed output is a valid DEFLATE stream but will
  92. * differ from vanilla zlib output ...
  93. */
  94. #if defined(CHROMIUM_ZLIB_NO_CASTAGNOLI)
  95. /* ... so this build-time option can used to disable the SIMD symbol hasher
  96. * if matching vanilla zlib DEFLATE output is required.
  97. */ (;) /* FALLTHOUGH */
  98. #elif defined(TARGET_CPU_WITH_CRC) && defined(CRC32_SIMD_SSE42_PCLMUL)
  99. if (x86_cpu_enable_simd)
  100. return insert_string_simd(s, str);
  101. #elif defined(TARGET_CPU_WITH_CRC) && defined(CRC32_ARMV8_CRC32)
  102. if (arm_cpu_enable_crc32)
  103. return insert_string_simd(s, str);
  104. #endif
  105. return insert_string_c(s, str);
  106. }