compare256_c.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /* compare256.c -- 256 byte memory comparison with match length return
  2. * Copyright (C) 2020 Nathan Moinvaziri
  3. * For conditions of distribution and use, see copyright notice in zlib.h
  4. */
  5. #include "zbuild.h"
  6. #include "zutil_p.h"
  7. #include "deflate.h"
  8. #include "fallback_builtins.h"
  9. /* ALIGNED, byte comparison */
  10. static inline uint32_t compare256_c_static(const uint8_t *src0, const uint8_t *src1) {
  11. uint32_t len = 0;
  12. do {
  13. if (*src0 != *src1)
  14. return len;
  15. src0 += 1, src1 += 1, len += 1;
  16. if (*src0 != *src1)
  17. return len;
  18. src0 += 1, src1 += 1, len += 1;
  19. if (*src0 != *src1)
  20. return len;
  21. src0 += 1, src1 += 1, len += 1;
  22. if (*src0 != *src1)
  23. return len;
  24. src0 += 1, src1 += 1, len += 1;
  25. if (*src0 != *src1)
  26. return len;
  27. src0 += 1, src1 += 1, len += 1;
  28. if (*src0 != *src1)
  29. return len;
  30. src0 += 1, src1 += 1, len += 1;
  31. if (*src0 != *src1)
  32. return len;
  33. src0 += 1, src1 += 1, len += 1;
  34. if (*src0 != *src1)
  35. return len;
  36. src0 += 1, src1 += 1, len += 1;
  37. } while (len < 256);
  38. return 256;
  39. }
  40. Z_INTERNAL uint32_t compare256_c(const uint8_t *src0, const uint8_t *src1) {
  41. return compare256_c_static(src0, src1);
  42. }
  43. #define LONGEST_MATCH longest_match_c
  44. #define COMPARE256 compare256_c_static
  45. #include "match_tpl.h"
  46. #define LONGEST_MATCH_SLOW
  47. #define LONGEST_MATCH longest_match_slow_c
  48. #define COMPARE256 compare256_c_static
  49. #include "match_tpl.h"
  50. #if defined(UNALIGNED_OK) && BYTE_ORDER == LITTLE_ENDIAN
  51. /* 16-bit unaligned integer comparison */
  52. static inline uint32_t compare256_unaligned_16_static(const uint8_t *src0, const uint8_t *src1) {
  53. uint32_t len = 0;
  54. do {
  55. if (zng_memcmp_2(src0, src1) != 0)
  56. return len + (*src0 == *src1);
  57. src0 += 2, src1 += 2, len += 2;
  58. if (zng_memcmp_2(src0, src1) != 0)
  59. return len + (*src0 == *src1);
  60. src0 += 2, src1 += 2, len += 2;
  61. if (zng_memcmp_2(src0, src1) != 0)
  62. return len + (*src0 == *src1);
  63. src0 += 2, src1 += 2, len += 2;
  64. if (zng_memcmp_2(src0, src1) != 0)
  65. return len + (*src0 == *src1);
  66. src0 += 2, src1 += 2, len += 2;
  67. } while (len < 256);
  68. return 256;
  69. }
  70. Z_INTERNAL uint32_t compare256_unaligned_16(const uint8_t *src0, const uint8_t *src1) {
  71. return compare256_unaligned_16_static(src0, src1);
  72. }
  73. #define LONGEST_MATCH longest_match_unaligned_16
  74. #define COMPARE256 compare256_unaligned_16_static
  75. #include "match_tpl.h"
  76. #define LONGEST_MATCH_SLOW
  77. #define LONGEST_MATCH longest_match_slow_unaligned_16
  78. #define COMPARE256 compare256_unaligned_16_static
  79. #include "match_tpl.h"
  80. #ifdef HAVE_BUILTIN_CTZ
  81. /* 32-bit unaligned integer comparison */
  82. static inline uint32_t compare256_unaligned_32_static(const uint8_t *src0, const uint8_t *src1) {
  83. uint32_t len = 0;
  84. do {
  85. uint32_t sv, mv, diff;
  86. memcpy(&sv, src0, sizeof(sv));
  87. memcpy(&mv, src1, sizeof(mv));
  88. diff = sv ^ mv;
  89. if (diff) {
  90. uint32_t match_byte = __builtin_ctz(diff) / 8;
  91. return len + match_byte;
  92. }
  93. src0 += 4, src1 += 4, len += 4;
  94. } while (len < 256);
  95. return 256;
  96. }
  97. Z_INTERNAL uint32_t compare256_unaligned_32(const uint8_t *src0, const uint8_t *src1) {
  98. return compare256_unaligned_32_static(src0, src1);
  99. }
  100. #define LONGEST_MATCH longest_match_unaligned_32
  101. #define COMPARE256 compare256_unaligned_32_static
  102. #include "match_tpl.h"
  103. #define LONGEST_MATCH_SLOW
  104. #define LONGEST_MATCH longest_match_slow_unaligned_32
  105. #define COMPARE256 compare256_unaligned_32_static
  106. #include "match_tpl.h"
  107. #endif
  108. #if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL)
  109. /* UNALIGNED64_OK, 64-bit integer comparison */
  110. static inline uint32_t compare256_unaligned_64_static(const uint8_t *src0, const uint8_t *src1) {
  111. uint32_t len = 0;
  112. do {
  113. uint64_t sv, mv, diff;
  114. memcpy(&sv, src0, sizeof(sv));
  115. memcpy(&mv, src1, sizeof(mv));
  116. diff = sv ^ mv;
  117. if (diff) {
  118. uint64_t match_byte = __builtin_ctzll(diff) / 8;
  119. return len + (uint32_t)match_byte;
  120. }
  121. src0 += 8, src1 += 8, len += 8;
  122. } while (len < 256);
  123. return 256;
  124. }
  125. Z_INTERNAL uint32_t compare256_unaligned_64(const uint8_t *src0, const uint8_t *src1) {
  126. return compare256_unaligned_64_static(src0, src1);
  127. }
  128. #define LONGEST_MATCH longest_match_unaligned_64
  129. #define COMPARE256 compare256_unaligned_64_static
  130. #include "match_tpl.h"
  131. #define LONGEST_MATCH_SLOW
  132. #define LONGEST_MATCH longest_match_slow_unaligned_64
  133. #define COMPARE256 compare256_unaligned_64_static
  134. #include "match_tpl.h"
  135. #endif
  136. #endif