_ZN6snappy6SourceD2Ev:
   36|  1.16k|Source::~Source() = default;
_ZNK6snappy15ByteArraySource9AvailableEv:
   68|  1.16k|size_t ByteArraySource::Available() const { return left_; }
_ZN6snappy15ByteArraySource4PeekEPm:
   70|  3.80k|const char* ByteArraySource::Peek(size_t* len) {
   71|  3.80k|  *len = left_;
   72|  3.80k|  return ptr_;
   73|  3.80k|}
_ZN6snappy15ByteArraySource4SkipEm:
   75|  5.90k|void ByteArraySource::Skip(size_t n) {
   76|  5.90k|  left_ -= n;
   77|  5.90k|  ptr_ += n;
   78|  5.90k|}

_ZN6snappy15ByteArraySourceC2EPKcm:
  148|  1.16k|  ByteArraySource(const char* p, size_t n) : ptr_(p), left_(n) { }
_ZN6snappy6SourceC2Ev:
  113|  1.16k|  Source() { }

_ZN6snappy6Varint16Parse32WithLimitEPKcS2_Pj:
  457|  2.39k|                                            uint32_t* OUTPUT) {
  458|  2.39k|  const unsigned char* ptr = reinterpret_cast<const unsigned char*>(p);
  459|  2.39k|  const unsigned char* limit = reinterpret_cast<const unsigned char*>(l);
  460|  2.39k|  uint32_t b, result;
  461|  2.39k|  if (ptr >= limit) return NULL;
  ------------------
  |  Branch (461:7): [True: 0, False: 2.39k]
  ------------------
  462|  2.39k|  b = *(ptr++); result = b & 127;          if (b < 128) goto done;
  ------------------
  |  Branch (462:48): [True: 1.03k, False: 1.36k]
  ------------------
  463|  1.36k|  if (ptr >= limit) return NULL;
  ------------------
  |  Branch (463:7): [True: 10, False: 1.35k]
  ------------------
  464|  1.35k|  b = *(ptr++); result |= (b & 127) <<  7; if (b < 128) goto done;
  ------------------
  |  Branch (464:48): [True: 830, False: 520]
  ------------------
  465|    520|  if (ptr >= limit) return NULL;
  ------------------
  |  Branch (465:7): [True: 9, False: 511]
  ------------------
  466|    511|  b = *(ptr++); result |= (b & 127) << 14; if (b < 128) goto done;
  ------------------
  |  Branch (466:48): [True: 310, False: 201]
  ------------------
  467|    201|  if (ptr >= limit) return NULL;
  ------------------
  |  Branch (467:7): [True: 9, False: 192]
  ------------------
  468|    192|  b = *(ptr++); result |= (b & 127) << 21; if (b < 128) goto done;
  ------------------
  |  Branch (468:48): [True: 38, False: 154]
  ------------------
  469|    154|  if (ptr >= limit) return NULL;
  ------------------
  |  Branch (469:7): [True: 9, False: 145]
  ------------------
  470|    145|  b = *(ptr++); result |= (b & 127) << 28; if (b < 16) goto done;
  ------------------
  |  Branch (470:48): [True: 135, False: 10]
  ------------------
  471|     10|  return NULL;       // Value is too long to be a varint32
  472|  2.34k| done:
  473|  2.34k|  *OUTPUT = result;
  474|  2.34k|  return reinterpret_cast<const char*>(ptr);
  475|    145|}
_ZN6snappy12LittleEndian6Load32EPKv:
  196|   235k|  static inline uint32_t Load32(const void *ptr) {
  197|       |    // Compiles to a single mov/str on recent clang and gcc.
  198|       |#if SNAPPY_IS_BIG_ENDIAN
  199|       |    const uint8_t* const buffer = reinterpret_cast<const uint8_t*>(ptr);
  200|       |    return (static_cast<uint32_t>(buffer[0])) |
  201|       |            (static_cast<uint32_t>(buffer[1]) << 8) |
  202|       |            (static_cast<uint32_t>(buffer[2]) << 16) |
  203|       |            (static_cast<uint32_t>(buffer[3]) << 24);
  204|       |#else
  205|       |    // See Load16() for the rationale of using memcpy().
  206|   235k|    uint32_t value;
  207|   235k|    std::memcpy(&value, ptr, 4);
  208|   235k|    return value;
  209|   235k|#endif
  210|   235k|  }
_ZN6snappy28STLStringResizeUninitializedEPNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEm:
  509|  1.16k|inline void STLStringResizeUninitialized(std::string* s, size_t new_size) {
  510|  1.16k|  s->resize(new_size);
  511|  1.16k|}
_ZN6snappy15string_as_arrayEPNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  525|  1.16k|inline char* string_as_array(std::string* str) {
  526|  1.16k|  return str->empty() ? NULL : &*str->begin();
  ------------------
  |  Branch (526:10): [True: 46, False: 1.11k]
  ------------------
  527|  1.16k|}

_ZN6snappy21GetUncompressedLengthEPKcmPm:
  726|  2.39k|bool GetUncompressedLength(const char* start, size_t n, size_t* result) {
  727|  2.39k|  uint32_t v = 0;
  728|  2.39k|  const char* limit = start + n;
  729|  2.39k|  if (Varint::Parse32WithLimit(start, limit, &v) != NULL) {
  ------------------
  |  Branch (729:7): [True: 2.34k, False: 47]
  ------------------
  730|  2.34k|    *result = v;
  731|  2.34k|    return true;
  732|  2.34k|  } else {
  733|     47|    return false;
  734|     47|  }
  735|  2.39k|}
_ZN6snappy9MemCopy64EPcPKvm:
 1227|   224k|void MemCopy64(char* dst, const void* src, size_t size) {
 1228|       |  // Always copy this many bytes.  If that's below size then copy the full 64.
 1229|   224k|  constexpr int kShortMemCopy = 32;
 1230|       |
 1231|   224k|  assert(size <= 64);
 1232|   224k|  assert(std::less_equal<const void*>()(static_cast<const char*>(src) + size,
 1233|   224k|                                        dst) ||
 1234|   224k|         std::less_equal<const void*>()(dst + size, src));
 1235|       |
 1236|       |  // We know that src and dst are at least size bytes apart. However, because we
 1237|       |  // might copy more than size bytes the copy still might overlap past size.
 1238|       |  // E.g. if src and dst appear consecutively in memory (src + size >= dst).
 1239|       |  // TODO: Investigate wider copies on other platforms.
 1240|       |#if defined(__x86_64__) && defined(__AVX__)
 1241|       |  assert(kShortMemCopy <= 32);
 1242|       |  __m256i data = _mm256_lddqu_si256(static_cast<const __m256i *>(src));
 1243|       |  _mm256_storeu_si256(reinterpret_cast<__m256i *>(dst), data);
 1244|       |  // Profiling shows that nearly all copies are short.
 1245|       |  if (SNAPPY_PREDICT_FALSE(size > kShortMemCopy)) {
 1246|       |    data = _mm256_lddqu_si256(static_cast<const __m256i *>(src) + 1);
 1247|       |    _mm256_storeu_si256(reinterpret_cast<__m256i *>(dst) + 1, data);
 1248|       |  }
 1249|       |#else
 1250|   224k|  std::memmove(dst, src, kShortMemCopy);
 1251|       |  // Profiling shows that nearly all copies are short.
 1252|   224k|  if (SNAPPY_PREDICT_FALSE(size > kShortMemCopy)) {
  ------------------
  |  |   94|   224k|#define SNAPPY_PREDICT_FALSE(x) (__builtin_expect(x, 0))
  |  |  ------------------
  |  |  |  Branch (94:33): [True: 6.93k, False: 218k]
  |  |  ------------------
  ------------------
 1253|  6.93k|    std::memmove(dst + kShortMemCopy,
 1254|  6.93k|                 static_cast<const uint8_t*>(src) + kShortMemCopy,
 1255|  6.93k|                 64 - kShortMemCopy);
 1256|  6.93k|  }
 1257|   224k|#endif
 1258|   224k|}
_ZN6snappy13ClearDeferredEPPKvPmPh:
 1268|   215k|                   uint8_t* safe_source) {
 1269|   215k|  *deferred_src = safe_source;
 1270|   215k|  *deferred_length = 0;
 1271|   215k|}
_ZN6snappy12DeferMemCopyEPPKvPmS1_m:
 1274|  21.7k|                  const void* src, size_t length) {
 1275|  21.7k|  *deferred_src = src;
 1276|  21.7k|  *deferred_length = length;
 1277|  21.7k|}
_ZN6snappy18SnappyDecompressor9RefillTagEv:
 1704|  2.23k|bool SnappyDecompressor::RefillTag() {
 1705|  2.23k|  const char* ip = ip_;
 1706|  2.23k|  if (ip == ip_limit_) {
  ------------------
  |  Branch (1706:7): [True: 1.43k, False: 808]
  ------------------
 1707|       |    // Fetch a new fragment from the reader
 1708|  1.43k|    reader_->Skip(peeked_);  // All peeked bytes are used up
 1709|  1.43k|    size_t n;
 1710|  1.43k|    ip = reader_->Peek(&n);
 1711|  1.43k|    peeked_ = n;
 1712|  1.43k|    eof_ = (n == 0);
 1713|  1.43k|    if (eof_) return false;
  ------------------
  |  Branch (1713:9): [True: 331, False: 1.10k]
  ------------------
 1714|  1.10k|    ip_limit_ = ip + n;
 1715|  1.10k|  }
 1716|       |
 1717|       |  // Read the tag character
 1718|  1.90k|  assert(ip < ip_limit_);
 1719|  1.90k|  const unsigned char c = *(reinterpret_cast<const unsigned char*>(ip));
 1720|       |  // At this point make sure that the data for the next tag is consecutive.
 1721|       |  // For copy 1 this means the next 2 bytes (tag and 1 byte offset)
 1722|       |  // For copy 2 the next 3 bytes (tag and 2 byte offset)
 1723|       |  // For copy 4 the next 5 bytes (tag and 4 byte offset)
 1724|       |  // For all small literals we only need 1 byte buf for literals 60...63 the
 1725|       |  // length is encoded in 1...4 extra bytes.
 1726|  1.90k|  const uint32_t needed = CalculateNeeded(c);
 1727|  1.90k|  assert(needed <= sizeof(scratch_));
 1728|       |
 1729|       |  // Read more bytes from reader if needed
 1730|  1.90k|  uint64_t nbuf = ip_limit_ - ip;
 1731|  1.90k|  if (nbuf < needed) {
  ------------------
  |  Branch (1731:7): [True: 28, False: 1.88k]
  ------------------
 1732|       |    // Stitch together bytes from ip and reader to form the word
 1733|       |    // contents.  We store the needed bytes in "scratch_".  They
 1734|       |    // will be consumed immediately by the caller since we do not
 1735|       |    // read more than we need.
 1736|     28|    std::memmove(scratch_, ip, nbuf);
 1737|     28|    reader_->Skip(peeked_);  // All peeked bytes are used up
 1738|     28|    peeked_ = 0;
 1739|     28|    while (nbuf < needed) {
  ------------------
  |  Branch (1739:12): [True: 28, False: 0]
  ------------------
 1740|     28|      size_t length;
 1741|     28|      const char* src = reader_->Peek(&length);
 1742|     28|      if (length == 0) return false;
  ------------------
  |  Branch (1742:11): [True: 28, False: 0]
  ------------------
 1743|      0|      uint64_t to_add = std::min<uint64_t>(needed - nbuf, length);
 1744|      0|      std::memcpy(scratch_ + nbuf, src, to_add);
 1745|      0|      nbuf += to_add;
 1746|      0|      reader_->Skip(to_add);
 1747|      0|    }
 1748|      0|    assert(nbuf == needed);
 1749|      0|    ip_ = scratch_;
 1750|      0|    ip_limit_ = scratch_ + needed;
 1751|  1.88k|  } else if (nbuf < kMaximumTagLength) {
  ------------------
  |  Branch (1751:14): [True: 932, False: 948]
  ------------------
 1752|       |    // Have enough bytes, but move into scratch_ so that we do not
 1753|       |    // read past end of input
 1754|    932|    std::memmove(scratch_, ip, nbuf);
 1755|    932|    reader_->Skip(peeked_);  // All peeked bytes are used up
 1756|    932|    peeked_ = 0;
 1757|    932|    ip_ = scratch_;
 1758|    932|    ip_limit_ = scratch_ + nbuf;
 1759|    948|  } else {
 1760|       |    // Pass pointer to buffer returned by reader_.
 1761|    948|    ip_ = ip;
 1762|    948|  }
 1763|  1.88k|  return true;
 1764|  1.90k|}
_ZN6snappy13RawUncompressEPKcmPc:
 2228|  1.16k|                   char* uncompressed) {
 2229|  1.16k|  ByteArraySource reader(compressed, compressed_length);
 2230|  1.16k|  return RawUncompress(&reader, uncompressed);
 2231|  1.16k|}
_ZN6snappy13RawUncompressEPNS_6SourceEPc:
 2233|  1.16k|bool RawUncompress(Source* compressed, char* uncompressed) {
 2234|  1.16k|  SnappyArrayWriter output(uncompressed);
 2235|  1.16k|  return InternalUncompress(compressed, &output);
 2236|  1.16k|}
_ZN6snappy10UncompressEPKcmPNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
 2239|  1.16k|                std::string* uncompressed) {
 2240|  1.16k|  size_t ulength;
 2241|  1.16k|  if (!GetUncompressedLength(compressed, compressed_length, &ulength)) {
  ------------------
  |  Branch (2241:7): [True: 0, False: 1.16k]
  ------------------
 2242|      0|    return false;
 2243|      0|  }
 2244|       |  // On 32-bit builds: max_size() < kuint32max.  Check for that instead
 2245|       |  // of crashing (e.g., consider externally specified compressed data).
 2246|  1.16k|  if (ulength > uncompressed->max_size()) {
  ------------------
  |  Branch (2246:7): [True: 0, False: 1.16k]
  ------------------
 2247|      0|    return false;
 2248|      0|  }
 2249|  1.16k|  STLStringResizeUninitialized(uncompressed, ulength);
 2250|  1.16k|  return RawUncompress(compressed, compressed_length,
 2251|  1.16k|                       string_as_array(uncompressed));
 2252|  1.16k|}
snappy.cc:_ZN6snappy12_GLOBAL__N_116UnalignedCopy128EPKvPv:
  229|  2.29k|void UnalignedCopy128(const void* src, void* dst) {
  230|       |  // std::memcpy() gets vectorized when the appropriate compiler options are
  231|       |  // used. For example, x86 compilers targeting SSE2+ will optimize to an SSE2
  232|       |  // load and store.
  233|  2.29k|  char tmp[16];
  234|  2.29k|  std::memcpy(tmp, src, 16);
  235|  2.29k|  std::memcpy(dst, tmp, 16);
  236|  2.29k|}
_ZN6snappy15CalculateNeededEh:
 1684|  1.90k|constexpr uint32_t CalculateNeeded(uint8_t tag) {
 1685|  1.90k|  return ((tag & 3) == 0 && tag >= (60 * 4))
  ------------------
  |  Branch (1685:11): [True: 1.26k, False: 644]
  |  Branch (1685:29): [True: 183, False: 1.08k]
  ------------------
 1686|  1.90k|             ? (tag >> 2) - 58
 1687|  1.90k|             : (0x05030201 >> ((tag * 8) & 31)) & 0xFF;
 1688|  1.90k|}
_ZN6snappy18SnappyDecompressorC2EPNS_6SourceE:
 1520|  1.16k|      : reader_(reader), ip_(NULL), ip_limit_(NULL), peeked_(0), eof_(false) {}
_ZN6snappy18SnappyDecompressor22ReadUncompressedLengthEPj:
 1533|  1.16k|  bool ReadUncompressedLength(uint32_t* result) {
 1534|  1.16k|    assert(ip_ == NULL);  // Must not have read anything yet
 1535|       |    // Length is encoded in 1..5 bytes
 1536|  1.16k|    *result = 0;
 1537|  1.16k|    uint32_t shift = 0;
 1538|  2.18k|    while (true) {
  ------------------
  |  Branch (1538:12): [Folded - Ignored]
  ------------------
 1539|  2.18k|      if (shift >= 32) return false;
  ------------------
  |  Branch (1539:11): [True: 0, False: 2.18k]
  ------------------
 1540|  2.18k|      size_t n;
 1541|  2.18k|      const char* ip = reader_->Peek(&n);
 1542|  2.18k|      if (n == 0) return false;
  ------------------
  |  Branch (1542:11): [True: 0, False: 2.18k]
  ------------------
 1543|  2.18k|      const unsigned char c = *(reinterpret_cast<const unsigned char*>(ip));
 1544|  2.18k|      reader_->Skip(1);
 1545|  2.18k|      uint32_t val = c & 0x7f;
 1546|  2.18k|      if (LeftShiftOverflows(static_cast<uint8_t>(val), shift)) return false;
  ------------------
  |  Branch (1546:11): [True: 0, False: 2.18k]
  ------------------
 1547|  2.18k|      *result |= val << shift;
 1548|  2.18k|      if (c < 128) {
  ------------------
  |  Branch (1548:11): [True: 1.16k, False: 1.02k]
  ------------------
 1549|  1.16k|        break;
 1550|  1.16k|      }
 1551|  1.02k|      shift += 7;
 1552|  1.02k|    }
 1553|  1.16k|    return true;
 1554|  1.16k|  }
snappy.cc:_ZN6snappyL18LeftShiftOverflowsEhj:
 1207|  2.18k|static inline bool LeftShiftOverflows(uint8_t value, uint32_t shift) {
 1208|  2.18k|  assert(shift < 32);
 1209|  2.18k|  static const uint8_t masks[] = {
 1210|  2.18k|      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  //
 1211|  2.18k|      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  //
 1212|  2.18k|      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  //
 1213|  2.18k|      0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe};
 1214|  2.18k|  return (value & masks[shift]) != 0;
 1215|  2.18k|}
_ZN6snappy18SnappyDecompressorD2Ev:
 1522|  1.16k|  ~SnappyDecompressor() {
 1523|       |    // Advance past any bytes we peeked at from the reader
 1524|  1.16k|    reader_->Skip(peeked_);
 1525|  1.16k|  }
snappy.cc:_ZN6snappyL6ReportEiPKcmm:
 1130|  1.16k|compressed_size, size_t uncompressed_size) {
 1131|       |  // TODO: Switch to [[maybe_unused]] when we can assume C++17.
 1132|  1.16k|  (void)token;
 1133|  1.16k|  (void)algorithm;
 1134|  1.16k|  (void)compressed_size;
 1135|  1.16k|  (void)uncompressed_size;
 1136|  1.16k|}
_ZN6snappy17SnappyArrayWriterC2EPc:
 2156|  1.16k|      : base_(dst),
 2157|  1.16k|        op_(dst),
 2158|  1.16k|        op_limit_(dst),
 2159|  1.16k|        op_limit_min_slop_(dst) {}  // Safe default see invariant.
_ZN6snappy18SnappyDecompressor10ResetLimitEPKc:
 1513|  3.04k|  void ResetLimit(const char* ip) {
 1514|  3.04k|    ip_limit_min_maxtaglen_ =
 1515|  3.04k|        ip_limit_ - std::min<ptrdiff_t>(ip_limit_ - ip, kMaximumTagLength - 1);
 1516|  3.04k|  }
_ZN6snappy20DecompressBranchlessIPcEENSt3__14pairIPKhlEES5_S5_lT_l:
 1382|  12.7k|    ptrdiff_t op_limit_min_slop) {
 1383|       |  // If deferred_src is invalid point it here.
 1384|  12.7k|  uint8_t safe_source[64];
 1385|  12.7k|  const void* deferred_src;
 1386|  12.7k|  size_t deferred_length;
 1387|  12.7k|  ClearDeferred(&deferred_src, &deferred_length, safe_source);
 1388|       |
 1389|       |  // We unroll the inner loop twice so we need twice the spare room.
 1390|  12.7k|  op_limit_min_slop -= kSlopBytes;
 1391|  12.7k|  if (2 * (kSlopBytes + 1) < ip_limit - ip && op < op_limit_min_slop) {
  ------------------
  |  Branch (1391:7): [True: 4.44k, False: 8.26k]
  |  Branch (1391:47): [True: 2.91k, False: 1.53k]
  ------------------
 1392|  2.91k|    const uint8_t* const ip_limit_min_slop = ip_limit - 2 * kSlopBytes - 1;
 1393|  2.91k|    ip++;
 1394|       |    // ip points just past the tag and we are touching at maximum kSlopBytes
 1395|       |    // in an iteration.
 1396|  2.91k|    size_t tag = ip[-1];
 1397|       |#if defined(__clang__) && defined(__aarch64__)
 1398|       |    // Workaround for https://bugs.llvm.org/show_bug.cgi?id=51317
 1399|       |    // when loading 1 byte, clang for aarch64 doesn't realize that it(ldrb)
 1400|       |    // comes with free zero-extension, so clang generates another
 1401|       |    // 'and xn, xm, 0xff' before it use that as the offset. This 'and' is
 1402|       |    // redundant and can be removed by adding this dummy asm, which gives
 1403|       |    // clang a hint that we're doing the zero-extension at the load.
 1404|       |    asm("" ::"r"(tag));
 1405|       |#endif
 1406|   113k|    do {
 1407|       |      // The throughput is limited by instructions, unrolling the inner loop
 1408|       |      // twice reduces the amount of instructions checking limits and also
 1409|       |      // leads to reduced mov's.
 1410|       |
 1411|   113k|      SNAPPY_PREFETCH(ip + 128);
  ------------------
  |  |  109|   113k|#define SNAPPY_PREFETCH(ptr) __builtin_prefetch(ptr, 0, 3)
  ------------------
 1412|   337k|      for (int i = 0; i < 2; i++) {
  ------------------
  |  Branch (1412:23): [True: 226k, False: 111k]
  ------------------
 1413|   226k|        const uint8_t* old_ip = ip;
 1414|   226k|        assert(tag == ip[-1]);
 1415|       |        // For literals tag_type = 0, hence we will always obtain 0 from
 1416|       |        // ExtractLowBytes. For literals offset will thus be kLiteralOffset.
 1417|   226k|        ptrdiff_t len_minus_offset = kLengthMinusOffset[tag];
 1418|   226k|        uint32_t next;
 1419|       |#if defined(__aarch64__)
 1420|       |        size_t tag_type = AdvanceToNextTagARMOptimized(&ip, &tag);
 1421|       |        // We never need more than 16 bits. Doing a Load16 allows the compiler
 1422|       |        // to elide the masking operation in ExtractOffset.
 1423|       |        next = LittleEndian::Load16(old_ip);
 1424|       |#else
 1425|   226k|        size_t tag_type = AdvanceToNextTagX86Optimized(&ip, &tag);
 1426|   226k|        next = LittleEndian::Load32(old_ip);
 1427|   226k|#endif
 1428|   226k|        size_t len = len_minus_offset & 0xFF;
 1429|   226k|        ptrdiff_t extracted = ExtractOffset(next, tag_type);
 1430|   226k|        ptrdiff_t len_min_offset = len_minus_offset - extracted;
 1431|   226k|        if (SNAPPY_PREDICT_FALSE(len_minus_offset > extracted)) {
  ------------------
  |  |   94|   226k|#define SNAPPY_PREDICT_FALSE(x) (__builtin_expect(x, 0))
  |  |  ------------------
  |  |  |  Branch (94:33): [True: 204k, False: 21.7k]
  |  |  ------------------
  ------------------
 1432|   204k|          if (SNAPPY_PREDICT_FALSE(len & 0x80)) {
  ------------------
  |  |   94|   204k|#define SNAPPY_PREDICT_FALSE(x) (__builtin_expect(x, 0))
  |  |  ------------------
  |  |  |  Branch (94:33): [True: 2.55k, False: 201k]
  |  |  ------------------
  ------------------
 1433|       |            // Exceptional case (long literal or copy 4).
 1434|       |            // Actually doing the copy here is negatively impacting the main
 1435|       |            // loop due to compiler incorrectly allocating a register for
 1436|       |            // this fallback. Hence we just break.
 1437|  2.63k|          break_loop:
 1438|  2.63k|            ip = old_ip;
 1439|  2.63k|            goto exit;
 1440|  2.55k|          }
 1441|       |          // Only copy-1 or copy-2 tags can get here.
 1442|   201k|          assert(tag_type == 1 || tag_type == 2);
 1443|   201k|          std::ptrdiff_t delta = (op + deferred_length) + len_min_offset - len;
 1444|       |          // Guard against copies before the buffer start.
 1445|       |          // Execute any deferred MemCopy since we write to dst here.
 1446|   201k|          MemCopy64(op_base + op, deferred_src, deferred_length);
 1447|   201k|          op += deferred_length;
 1448|   201k|          ClearDeferred(&deferred_src, &deferred_length, safe_source);
 1449|   201k|          if (SNAPPY_PREDICT_FALSE(delta < 0 ||
  ------------------
  |  |   94|   403k|#define SNAPPY_PREDICT_FALSE(x) (__builtin_expect(x, 0))
  |  |  ------------------
  |  |  |  Branch (94:33): [True: 32, False: 201k]
  |  |  |  Branch (94:51): [True: 10, False: 201k]
  |  |  |  Branch (94:51): [True: 22, False: 201k]
  |  |  ------------------
  ------------------
 1450|   201k|                                  !Copy64BytesWithPatternExtension(
 1451|   201k|                                      op_base + op, len - len_min_offset))) {
 1452|     32|            goto break_loop;
 1453|     32|          }
 1454|       |          // We aren't deferring this copy so add length right away.
 1455|   201k|          op += len;
 1456|   201k|          continue;
 1457|   201k|        }
 1458|  21.7k|        std::ptrdiff_t delta = (op + deferred_length) + len_min_offset - len;
 1459|  21.7k|        if (SNAPPY_PREDICT_FALSE(delta < 0)) {
  ------------------
  |  |   94|  21.7k|#define SNAPPY_PREDICT_FALSE(x) (__builtin_expect(x, 0))
  |  |  ------------------
  |  |  |  Branch (94:33): [True: 2.27k, False: 19.5k]
  |  |  ------------------
  ------------------
 1460|       |          // Due to the spurious offset in literals have this will trigger
 1461|       |          // at the start of a block when op is still smaller than 256.
 1462|  2.27k|          if (tag_type != 0) goto break_loop;
  ------------------
  |  Branch (1462:15): [True: 52, False: 2.22k]
  ------------------
 1463|  2.22k|          MemCopy64(op_base + op, deferred_src, deferred_length);
 1464|  2.22k|          op += deferred_length;
 1465|  2.22k|          DeferMemCopy(&deferred_src, &deferred_length, old_ip, len);
 1466|  2.22k|          continue;
 1467|  2.27k|        }
 1468|       |
 1469|       |        // For copies we need to copy from op_base + delta, for literals
 1470|       |        // we need to copy from ip instead of from the stream.
 1471|  19.5k|        const void* from =
 1472|  19.5k|            tag_type ? reinterpret_cast<void*>(op_base + delta) : old_ip;
  ------------------
  |  Branch (1472:13): [True: 8.16k, False: 11.3k]
  ------------------
 1473|  19.5k|        MemCopy64(op_base + op, deferred_src, deferred_length);
 1474|  19.5k|        op += deferred_length;
 1475|  19.5k|        DeferMemCopy(&deferred_src, &deferred_length, from, len);
 1476|  19.5k|      }
 1477|   113k|    } while (ip < ip_limit_min_slop &&
  ------------------
  |  Branch (1477:14): [True: 110k, False: 266]
  ------------------
 1478|   111k|             static_cast<ptrdiff_t>(op + deferred_length) < op_limit_min_slop);
  ------------------
  |  Branch (1478:14): [True: 110k, False: 11]
  ------------------
 1479|  2.91k|  exit:
 1480|  2.91k|    ip--;
 1481|  2.91k|    assert(ip <= ip_limit);
 1482|  2.91k|  }
 1483|       |  // If we deferred a copy then we can perform.  If we are up to date then we
 1484|       |  // might not have enough slop bytes and could run past the end.
 1485|  12.7k|  if (deferred_length) {
  ------------------
  |  Branch (1485:7): [True: 1.35k, False: 11.3k]
  ------------------
 1486|  1.35k|    MemCopy64(op_base + op, deferred_src, deferred_length);
 1487|  1.35k|    op += deferred_length;
 1488|  1.35k|    ClearDeferred(&deferred_src, &deferred_length, safe_source);
 1489|  1.35k|  }
 1490|  12.7k|  return {ip, op};
 1491|  12.7k|}
_ZN6snappy28AdvanceToNextTagX86OptimizedEPPKhPm:
 1303|   226k|inline size_t AdvanceToNextTagX86Optimized(const uint8_t** ip_p, size_t* tag) {
 1304|   226k|  const uint8_t*& ip = *ip_p;
 1305|       |  // This section is crucial for the throughput of the decompression loop.
 1306|       |  // The latency of an iteration is fundamentally constrained by the
 1307|       |  // following data chain on ip.
 1308|       |  // ip -> c = Load(ip) -> ip1 = ip + 1 + (c & 3) -> ip = ip1 or ip2
 1309|       |  //                       ip2 = ip + 2 + (c >> 2)
 1310|       |  // This amounts to 8 cycles.
 1311|       |  // 5 (load) + 1 (c & 3) + 1 (lea ip1, [ip + (c & 3) + 1]) + 1 (cmov)
 1312|   226k|  size_t literal_len = *tag >> 2;
 1313|   226k|  size_t tag_type = *tag;
 1314|   226k|  bool is_literal;
 1315|   226k|#if defined(__GCC_ASM_FLAG_OUTPUTS__) && defined(__x86_64__)
 1316|       |  // TODO clang misses the fact that the (c & 3) already correctly
 1317|       |  // sets the zero flag.
 1318|   226k|  asm("and $3, %k[tag_type]\n\t"
 1319|   226k|      : [tag_type] "+r"(tag_type), "=@ccz"(is_literal)
 1320|   226k|      :: "cc");
 1321|       |#else
 1322|       |  tag_type &= 3;
 1323|       |  is_literal = (tag_type == 0);
 1324|       |#endif
 1325|       |  // TODO
 1326|       |  // This is code is subtle. Loading the values first and then cmov has less
 1327|       |  // latency then cmov ip and then load. However clang would move the loads
 1328|       |  // in an optimization phase, volatile prevents this transformation.
 1329|       |  // Note that we have enough slop bytes (64) that the loads are always valid.
 1330|   226k|  size_t tag_literal =
 1331|   226k|      static_cast<const volatile uint8_t*>(ip)[1 + literal_len];
 1332|   226k|  size_t tag_copy = static_cast<const volatile uint8_t*>(ip)[tag_type];
 1333|   226k|  *tag = is_literal ? tag_literal : tag_copy;
  ------------------
  |  Branch (1333:10): [True: 15.3k, False: 210k]
  ------------------
 1334|   226k|  const uint8_t* ip_copy = ip + 1 + tag_type;
 1335|   226k|  const uint8_t* ip_literal = ip + 2 + literal_len;
 1336|   226k|  ip = is_literal ? ip_literal : ip_copy;
  ------------------
  |  Branch (1336:8): [True: 15.3k, False: 210k]
  ------------------
 1337|   226k|#if defined(__GNUC__) && defined(__x86_64__)
 1338|       |  // TODO Clang is "optimizing" zero-extension (a totally free
 1339|       |  // operation) this means that after the cmov of tag, it emits another movzb
 1340|       |  // tag, byte(tag). It really matters as it's on the core chain. This dummy
 1341|       |  // asm, persuades clang to do the zero-extension at the load (it's automatic)
 1342|       |  // removing the expensive movzb.
 1343|   226k|  asm("" ::"r"(tag_copy));
 1344|   226k|#endif
 1345|   226k|  return tag_type;
 1346|   226k|}
_ZN6snappy13ExtractOffsetEjm:
 1349|   226k|inline uint32_t ExtractOffset(uint32_t val, size_t tag_type) {
 1350|       |  // For x86 non-static storage works better. For ARM static storage is better.
 1351|       |  // TODO: Once the array is recognized as a register, improve the
 1352|       |  // readability for x86.
 1353|   226k|#if defined(__x86_64__)
 1354|   226k|  constexpr uint64_t kExtractMasksCombined = 0x0000FFFF00FF0000ull;
 1355|   226k|  uint16_t result;
 1356|   226k|  memcpy(&result,
 1357|   226k|         reinterpret_cast<const char*>(&kExtractMasksCombined) + 2 * tag_type,
 1358|   226k|         sizeof(result));
 1359|   226k|  return val & result;
 1360|       |#elif defined(__aarch64__)
 1361|       |  constexpr uint64_t kExtractMasksCombined = 0x0000FFFF00FF0000ull;
 1362|       |  return val & static_cast<uint32_t>(
 1363|       |      (kExtractMasksCombined >> (tag_type * 16)) & 0xFFFF);
 1364|       |#else
 1365|       |  static constexpr uint32_t kExtractMasks[4] = {0, 0xFF, 0xFFFF, 0};
 1366|       |  return val & kExtractMasks[tag_type];
 1367|       |#endif
 1368|   226k|};
snappy.cc:_ZN6snappy12_GLOBAL__N_131Copy64BytesWithPatternExtensionEPcm:
  356|   201k|static inline bool Copy64BytesWithPatternExtension(char* dst, size_t offset) {
  357|       |#if SNAPPY_HAVE_VECTOR_BYTE_SHUFFLE
  358|       |  if (SNAPPY_PREDICT_TRUE(offset <= 16)) {
  359|       |    switch (offset) {
  360|       |      case 0:
  361|       |        return false;
  362|       |      case 1: {
  363|       |        // TODO: Ideally we should memset, move back once the
  364|       |        // codegen issues are fixed.
  365|       |        V128 pattern = V128_DupChar(dst[-1]);
  366|       |        for (int i = 0; i < 4; i++) {
  367|       |          V128_StoreU(reinterpret_cast<V128*>(dst + 16 * i), pattern);
  368|       |        }
  369|       |        return true;
  370|       |      }
  371|       |      case 2:
  372|       |      case 4:
  373|       |      case 8:
  374|       |      case 16: {
  375|       |        V128 pattern = LoadPattern(dst - offset, offset);
  376|       |        for (int i = 0; i < 4; i++) {
  377|       |          V128_StoreU(reinterpret_cast<V128*>(dst + 16 * i), pattern);
  378|       |        }
  379|       |        return true;
  380|       |      }
  381|       |      default: {
  382|       |        auto pattern_and_reshuffle_mask =
  383|       |            LoadPatternAndReshuffleMask(dst - offset, offset);
  384|       |        V128 pattern = pattern_and_reshuffle_mask.first;
  385|       |        V128 reshuffle_mask = pattern_and_reshuffle_mask.second;
  386|       |        for (int i = 0; i < 4; i++) {
  387|       |          V128_StoreU(reinterpret_cast<V128*>(dst + 16 * i), pattern);
  388|       |          pattern = V128_Shuffle(pattern, reshuffle_mask);
  389|       |        }
  390|       |        return true;
  391|       |      }
  392|       |    }
  393|       |  }
  394|       |#else
  395|   201k|  if (SNAPPY_PREDICT_TRUE(offset < 16)) {
  ------------------
  |  |   95|   201k|#define SNAPPY_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
  |  |  ------------------
  |  |  |  Branch (95:32): [True: 176k, False: 24.8k]
  |  |  ------------------
  ------------------
  396|   176k|    if (SNAPPY_PREDICT_FALSE(offset == 0)) return false;
  ------------------
  |  |   94|   176k|#define SNAPPY_PREDICT_FALSE(x) (__builtin_expect(x, 0))
  |  |  ------------------
  |  |  |  Branch (94:33): [True: 22, False: 176k]
  |  |  ------------------
  ------------------
  397|       |    // Extend the pattern to the first 16 bytes.
  398|       |    // The simpler formulation of `dst[i - offset]` induces undefined behavior.
  399|  3.00M|    for (int i = 0; i < 16; i++) dst[i] = (dst - offset)[i];
  ------------------
  |  Branch (399:21): [True: 2.83M, False: 176k]
  ------------------
  400|       |    // Find a multiple of pattern >= 16.
  401|   176k|    static std::array<uint8_t, 16> pattern_sizes = []() {
  402|   176k|      std::array<uint8_t, 16> res;
  403|   176k|      for (int i = 1; i < 16; i++) res[i] = (16 / i + 1) * i;
  404|   176k|      return res;
  405|   176k|    }();
  406|   176k|    offset = pattern_sizes[offset];
  407|   707k|    for (int i = 1; i < 4; i++) {
  ------------------
  |  Branch (407:21): [True: 530k, False: 176k]
  ------------------
  408|   530k|      std::memcpy(dst + i * 16, dst + i * 16 - offset, 16);
  409|   530k|    }
  410|   176k|    return true;
  411|   176k|  }
  412|  24.8k|#endif  // SNAPPY_HAVE_VECTOR_BYTE_SHUFFLE
  413|       |
  414|       |  // Very rare.
  415|   124k|  for (int i = 0; i < 4; i++) {
  ------------------
  |  Branch (415:19): [True: 99.4k, False: 24.8k]
  ------------------
  416|  99.4k|    std::memcpy(dst + i * 16, dst + i * 16 - offset, 16);
  417|  99.4k|  }
  418|  24.8k|  return true;
  419|   201k|}
snappy.cc:_ZZN6snappy12_GLOBAL__N_131Copy64BytesWithPatternExtensionEPcmENKUlvE_clEv:
  401|      1|    static std::array<uint8_t, 16> pattern_sizes = []() {
  402|      1|      std::array<uint8_t, 16> res;
  403|     16|      for (int i = 1; i < 16; i++) res[i] = (16 / i + 1) * i;
  ------------------
  |  Branch (403:23): [True: 15, False: 1]
  ------------------
  404|      1|      return res;
  405|      1|    }();
snappy.cc:_ZN6snappyL15ExtractLowBytesERKji:
 1194|  8.26k|static inline uint32_t ExtractLowBytes(const uint32_t& v, int n) {
 1195|  8.26k|  assert(n >= 0);
 1196|  8.26k|  assert(n <= 4);
 1197|       |#if SNAPPY_HAVE_BMI2
 1198|       |  return _bzhi_u32(v, 8 * n);
 1199|       |#else
 1200|       |  // This needs to be wider than uint32_t otherwise `mask << 32` will be
 1201|       |  // undefined.
 1202|  8.26k|  uint64_t mask = 0xffffffff;
 1203|  8.26k|  return v & ~(mask << (8 * n));
 1204|  8.26k|#endif
 1205|  8.26k|}
snappy.cc:_ZN6snappy12_GLOBAL__N_115IncrementalCopyEPKcPcS3_S3_:
  425|  5.29k|                             char* const buf_limit) {
  426|       |#if SNAPPY_HAVE_VECTOR_BYTE_SHUFFLE
  427|       |  constexpr int big_pattern_size_lower_bound = 16;
  428|       |#else
  429|  5.29k|  constexpr int big_pattern_size_lower_bound = 8;
  430|  5.29k|#endif
  431|       |
  432|       |  // Terminology:
  433|       |  //
  434|       |  // slop = buf_limit - op
  435|       |  // pat  = op - src
  436|       |  // len  = op_limit - op
  437|  5.29k|  assert(src < op);
  438|  5.29k|  assert(op < op_limit);
  439|  5.29k|  assert(op_limit <= buf_limit);
  440|       |  // NOTE: The copy tags use 3 or 6 bits to store the copy length, so len <= 64.
  441|  5.29k|  assert(op_limit - op <= 64);
  442|       |  // NOTE: In practice the compressor always emits len >= 4, so it is ok to
  443|       |  // assume that to optimize this function, but this is not guaranteed by the
  444|       |  // compression format, so we have to also handle len < 4 in case the input
  445|       |  // does not satisfy these conditions.
  446|       |
  447|  5.29k|  size_t pattern_size = op - src;
  448|       |  // The cases are split into different branches to allow the branch predictor,
  449|       |  // FDO, and static prediction hints to work better. For each input we list the
  450|       |  // ratio of invocations that match each condition.
  451|       |  //
  452|       |  // input        slop < 16   pat < 8  len > 16
  453|       |  // ------------------------------------------
  454|       |  // html|html4|cp   0%         1.01%    27.73%
  455|       |  // urls            0%         0.88%    14.79%
  456|       |  // jpg             0%        64.29%     7.14%
  457|       |  // pdf             0%         2.56%    58.06%
  458|       |  // txt[1-4]        0%         0.23%     0.97%
  459|       |  // pb              0%         0.96%    13.88%
  460|       |  // bin             0.01%     22.27%    41.17%
  461|       |  //
  462|       |  // It is very rare that we don't have enough slop for doing block copies. It
  463|       |  // is also rare that we need to expand a pattern. Small patterns are common
  464|       |  // for incompressible formats and for those we are plenty fast already.
  465|       |  // Lengths are normally not greater than 16 but they vary depending on the
  466|       |  // input. In general if we always predict len <= 16 it would be an ok
  467|       |  // prediction.
  468|       |  //
  469|       |  // In order to be fast we want a pattern >= 16 bytes (or 8 bytes in non-SSE)
  470|       |  // and an unrolled loop copying 1x 16 bytes (or 2x 8 bytes in non-SSE) at a
  471|       |  // time.
  472|       |
  473|       |  // Handle the uncommon case where pattern is less than 16 (or 8 in non-SSE)
  474|       |  // bytes.
  475|  5.29k|  if (pattern_size < big_pattern_size_lower_bound) {
  ------------------
  |  Branch (475:7): [True: 3.76k, False: 1.52k]
  ------------------
  476|       |#if SNAPPY_HAVE_VECTOR_BYTE_SHUFFLE
  477|       |    // Load the first eight bytes into an 128-bit XMM register, then use PSHUFB
  478|       |    // to permute the register's contents in-place into a repeating sequence of
  479|       |    // the first "pattern_size" bytes.
  480|       |    // For example, suppose:
  481|       |    //    src       == "abc"
  482|       |    //    op        == op + 3
  483|       |    // After V128_Shuffle(), "pattern" will have five copies of "abc"
  484|       |    // followed by one byte of slop: abcabcabcabcabca.
  485|       |    //
  486|       |    // The non-SSE fallback implementation suffers from store-forwarding stalls
  487|       |    // because its loads and stores partly overlap. By expanding the pattern
  488|       |    // in-place, we avoid the penalty.
  489|       |
  490|       |    // Typically, the op_limit is the gating factor so try to simplify the loop
  491|       |    // based on that.
  492|       |    if (SNAPPY_PREDICT_TRUE(op_limit <= buf_limit - 15)) {
  493|       |      auto pattern_and_reshuffle_mask =
  494|       |          LoadPatternAndReshuffleMask(src, pattern_size);
  495|       |      V128 pattern = pattern_and_reshuffle_mask.first;
  496|       |      V128 reshuffle_mask = pattern_and_reshuffle_mask.second;
  497|       |
  498|       |      // There is at least one, and at most four 16-byte blocks. Writing four
  499|       |      // conditionals instead of a loop allows FDO to layout the code with
  500|       |      // respect to the actual probabilities of each length.
  501|       |      // TODO: Replace with loop with trip count hint.
  502|       |      V128_StoreU(reinterpret_cast<V128*>(op), pattern);
  503|       |
  504|       |      if (op + 16 < op_limit) {
  505|       |        pattern = V128_Shuffle(pattern, reshuffle_mask);
  506|       |        V128_StoreU(reinterpret_cast<V128*>(op + 16), pattern);
  507|       |      }
  508|       |      if (op + 32 < op_limit) {
  509|       |        pattern = V128_Shuffle(pattern, reshuffle_mask);
  510|       |        V128_StoreU(reinterpret_cast<V128*>(op + 32), pattern);
  511|       |      }
  512|       |      if (op + 48 < op_limit) {
  513|       |        pattern = V128_Shuffle(pattern, reshuffle_mask);
  514|       |        V128_StoreU(reinterpret_cast<V128*>(op + 48), pattern);
  515|       |      }
  516|       |      return op_limit;
  517|       |    }
  518|       |    char* const op_end = buf_limit - 15;
  519|       |    if (SNAPPY_PREDICT_TRUE(op < op_end)) {
  520|       |      auto pattern_and_reshuffle_mask =
  521|       |          LoadPatternAndReshuffleMask(src, pattern_size);
  522|       |      V128 pattern = pattern_and_reshuffle_mask.first;
  523|       |      V128 reshuffle_mask = pattern_and_reshuffle_mask.second;
  524|       |
  525|       |      // This code path is relatively cold however so we save code size
  526|       |      // by avoiding unrolling and vectorizing.
  527|       |      //
  528|       |      // TODO: Remove pragma when when cold regions don't get
  529|       |      // vectorized or unrolled.
  530|       |#ifdef __clang__
  531|       |#pragma clang loop unroll(disable)
  532|       |#endif
  533|       |      do {
  534|       |        V128_StoreU(reinterpret_cast<V128*>(op), pattern);
  535|       |        pattern = V128_Shuffle(pattern, reshuffle_mask);
  536|       |        op += 16;
  537|       |      } while (SNAPPY_PREDICT_TRUE(op < op_end));
  538|       |    }
  539|       |    return IncrementalCopySlow(op - pattern_size, op, op_limit);
  540|       |#else   // !SNAPPY_HAVE_VECTOR_BYTE_SHUFFLE
  541|       |    // If plenty of buffer space remains, expand the pattern to at least 8
  542|       |    // bytes. The way the following loop is written, we need 8 bytes of buffer
  543|       |    // space if pattern_size >= 4, 11 bytes if pattern_size is 1 or 3, and 10
  544|       |    // bytes if pattern_size is 2.  Precisely encoding that is probably not
  545|       |    // worthwhile; instead, invoke the slow path if we cannot write 11 bytes
  546|       |    // (because 11 are required in the worst case).
  547|  3.76k|    if (SNAPPY_PREDICT_TRUE(op <= buf_limit - 11)) {
  ------------------
  |  |   95|  3.76k|#define SNAPPY_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
  |  |  ------------------
  |  |  |  Branch (95:32): [True: 3.69k, False: 70]
  |  |  ------------------
  ------------------
  548|  14.0k|      while (pattern_size < 8) {
  ------------------
  |  Branch (548:14): [True: 10.3k, False: 3.69k]
  ------------------
  549|  10.3k|        UnalignedCopy64(src, op);
  550|  10.3k|        op += pattern_size;
  551|  10.3k|        pattern_size *= 2;
  552|  10.3k|      }
  553|  3.69k|      if (SNAPPY_PREDICT_TRUE(op >= op_limit)) return op_limit;
  ------------------
  |  |   95|  3.69k|#define SNAPPY_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
  |  |  ------------------
  |  |  |  Branch (95:32): [True: 768, False: 2.93k]
  |  |  ------------------
  ------------------
  554|  3.69k|    } else {
  555|     70|      return IncrementalCopySlow(src, op, op_limit);
  556|     70|    }
  557|  3.76k|#endif  // SNAPPY_HAVE_VECTOR_BYTE_SHUFFLE
  558|  3.76k|  }
  559|  4.45k|  assert(pattern_size >= big_pattern_size_lower_bound);
  560|  4.45k|  constexpr bool use_16bytes_chunk = big_pattern_size_lower_bound == 16;
  561|       |
  562|       |  // Copy 1x 16 bytes (or 2x 8 bytes in non-SSE) at a time. Because op - src can
  563|       |  // be < 16 in non-SSE, a single UnalignedCopy128 might overwrite data in op.
  564|       |  // UnalignedCopy64 is safe because expanding the pattern to at least 8 bytes
  565|       |  // guarantees that op - src >= 8.
  566|       |  //
  567|       |  // Typically, the op_limit is the gating factor so try to simplify the loop
  568|       |  // based on that.
  569|  4.45k|  if (SNAPPY_PREDICT_TRUE(op_limit <= buf_limit - 15)) {
  ------------------
  |  |   95|  4.45k|#define SNAPPY_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
  |  |  ------------------
  |  |  |  Branch (95:32): [True: 4.27k, False: 186]
  |  |  ------------------
  ------------------
  570|       |    // There is at least one, and at most four 16-byte blocks. Writing four
  571|       |    // conditionals instead of a loop allows FDO to layout the code with respect
  572|       |    // to the actual probabilities of each length.
  573|       |    // TODO: Replace with loop with trip count hint.
  574|  4.27k|    ConditionalUnalignedCopy128<use_16bytes_chunk>(src, op);
  575|  4.27k|    if (op + 16 < op_limit) {
  ------------------
  |  Branch (575:9): [True: 3.64k, False: 626]
  ------------------
  576|  3.64k|      ConditionalUnalignedCopy128<use_16bytes_chunk>(src + 16, op + 16);
  577|  3.64k|    }
  578|  4.27k|    if (op + 32 < op_limit) {
  ------------------
  |  Branch (578:9): [True: 3.60k, False: 666]
  ------------------
  579|  3.60k|      ConditionalUnalignedCopy128<use_16bytes_chunk>(src + 32, op + 32);
  580|  3.60k|    }
  581|  4.27k|    if (op + 48 < op_limit) {
  ------------------
  |  Branch (581:9): [True: 3.46k, False: 808]
  ------------------
  582|  3.46k|      ConditionalUnalignedCopy128<use_16bytes_chunk>(src + 48, op + 48);
  583|  3.46k|    }
  584|  4.27k|    return op_limit;
  585|  4.27k|  }
  586|       |
  587|       |  // Fall back to doing as much as we can with the available slop in the
  588|       |  // buffer. This code path is relatively cold however so we save code size by
  589|       |  // avoiding unrolling and vectorizing.
  590|       |  //
  591|       |  // TODO: Remove pragma when when cold regions don't get vectorized
  592|       |  // or unrolled.
  593|    186|#ifdef __clang__
  594|    186|#pragma clang loop unroll(disable)
  595|    186|#endif
  596|    271|  for (char* op_end = buf_limit - 16; op < op_end; op += 16, src += 16) {
  ------------------
  |  Branch (596:39): [True: 85, False: 186]
  ------------------
  597|     85|    ConditionalUnalignedCopy128<use_16bytes_chunk>(src, op);
  598|     85|  }
  599|    186|  if (op >= op_limit) return op_limit;
  ------------------
  |  Branch (599:7): [True: 18, False: 168]
  ------------------
  600|       |
  601|       |  // We only take this branch if we didn't have enough slop and we can do a
  602|       |  // single 8 byte copy.
  603|    168|  if (SNAPPY_PREDICT_FALSE(op <= buf_limit - 8)) {
  ------------------
  |  |   94|    168|#define SNAPPY_PREDICT_FALSE(x) (__builtin_expect(x, 0))
  |  |  ------------------
  |  |  |  Branch (94:33): [True: 100, False: 68]
  |  |  ------------------
  ------------------
  604|    100|    UnalignedCopy64(src, op);
  605|    100|    src += 8;
  606|    100|    op += 8;
  607|    100|  }
  608|    168|  return IncrementalCopySlow(src, op, op_limit);
  609|    186|}
snappy.cc:_ZN6snappy12_GLOBAL__N_115UnalignedCopy64EPKvPv:
  223|  40.6k|void UnalignedCopy64(const void* src, void* dst) {
  224|  40.6k|  char tmp[8];
  225|  40.6k|  std::memcpy(tmp, src, 8);
  226|  40.6k|  std::memcpy(dst, tmp, 8);
  227|  40.6k|}
snappy.cc:_ZN6snappy12_GLOBAL__N_119IncrementalCopySlowEPKcPcS3_:
  260|    238|                                 char* const op_limit) {
  261|       |  // TODO: Remove pragma when LLVM is aware this
  262|       |  // function is only called in cold regions and when cold regions don't get
  263|       |  // vectorized or unrolled.
  264|    238|#ifdef __clang__
  265|    238|#pragma clang loop unroll(disable)
  266|    238|#endif
  267|    540|  while (op < op_limit) {
  ------------------
  |  Branch (267:10): [True: 302, False: 238]
  ------------------
  268|    302|    *op++ = *src++;
  269|    302|  }
  270|    238|  return op_limit;
  271|    238|}
snappy.cc:_ZN6snappy12_GLOBAL__N_127ConditionalUnalignedCopy128ILb0EEEvPKcPc:
  239|  15.0k|inline void ConditionalUnalignedCopy128(const char* src, char* dst) {
  240|  15.0k|  if (use_16bytes_chunk) {
  ------------------
  |  Branch (240:7): [Folded - Ignored]
  ------------------
  241|      0|    UnalignedCopy128(src, dst);
  242|  15.0k|  } else {
  243|  15.0k|    UnalignedCopy64(src, dst);
  244|  15.0k|    UnalignedCopy64(src + 8, dst + 8);
  245|  15.0k|  }
  246|  15.0k|}
_ZNK6snappy18SnappyDecompressor3eofEv:
 1528|  1.16k|  bool eof() const { return eof_; }
snappy.cc:_ZN6snappyL18InternalUncompressINS_17SnappyArrayWriterEEEbPNS_6SourceEPT_:
 1767|  1.16k|static bool InternalUncompress(Source* r, Writer* writer) {
 1768|       |  // Read the uncompressed length from the front of the compressed input
 1769|  1.16k|  SnappyDecompressor decompressor(r);
 1770|  1.16k|  uint32_t uncompressed_len = 0;
 1771|  1.16k|  if (!decompressor.ReadUncompressedLength(&uncompressed_len)) return false;
  ------------------
  |  Branch (1771:7): [True: 0, False: 1.16k]
  ------------------
 1772|       |
 1773|  1.16k|  return InternalUncompressAllTags(&decompressor, writer, r->Available(),
 1774|  1.16k|                                   uncompressed_len);
 1775|  1.16k|}
snappy.cc:_ZN6snappyL25InternalUncompressAllTagsINS_17SnappyArrayWriterEEEbPNS_18SnappyDecompressorEPT_jj:
 1780|  1.16k|                                      uint32_t uncompressed_len) {
 1781|  1.16k|    int token = 0;
 1782|  1.16k|  Report(token, "snappy_uncompress", compressed_len, uncompressed_len);
 1783|       |
 1784|  1.16k|  writer->SetExpectedLength(uncompressed_len);
 1785|       |
 1786|       |  // Process the entire input
 1787|  1.16k|  decompressor->DecompressAllTags(writer);
 1788|  1.16k|  writer->Flush();
 1789|  1.16k|  return (decompressor->eof() && writer->CheckLength());
  ------------------
  |  Branch (1789:11): [True: 331, False: 834]
  |  Branch (1789:34): [True: 18, False: 313]
  ------------------
 1790|  1.16k|}
_ZN6snappy17SnappyArrayWriter17SetExpectedLengthEm:
 2161|  1.16k|  inline void SetExpectedLength(size_t len) {
 2162|  1.16k|    op_limit_ = op_ + len;
 2163|       |    // Prevent pointer from being past the buffer.
 2164|  1.16k|    op_limit_min_slop_ = op_limit_ - std::min<size_t>(kSlopBytes - 1, len);
 2165|  1.16k|  }
_ZN6snappy18SnappyDecompressor17DecompressAllTagsINS_17SnappyArrayWriterEEEvPT_:
 1563|  1.16k|  DecompressAllTags(Writer* writer) {
 1564|  1.16k|    const char* ip = ip_;
 1565|  1.16k|    ResetLimit(ip);
 1566|  1.16k|    auto op = writer->GetOutputPtr();
 1567|       |    // We could have put this refill fragment only at the beginning of the loop.
 1568|       |    // However, duplicating it at the end of each branch gives the compiler more
 1569|       |    // scope to optimize the <ip_limit_ - ip> expression based on the local
 1570|       |    // context, which overall increases speed.
 1571|  1.16k|#define MAYBE_REFILL()                                      \
 1572|  1.16k|  if (SNAPPY_PREDICT_FALSE(ip >= ip_limit_min_maxtaglen_)) { \
 1573|  1.16k|    ip_ = ip;                                               \
 1574|  1.16k|    if (SNAPPY_PREDICT_FALSE(!RefillTag())) goto exit;       \
 1575|  1.16k|    ip = ip_;                                               \
 1576|  1.16k|    ResetLimit(ip);                                         \
 1577|  1.16k|  }                                                         \
 1578|  1.16k|  preload = static_cast<uint8_t>(*ip)
 1579|       |
 1580|       |    // At the start of the for loop below the least significant byte of preload
 1581|       |    // contains the tag.
 1582|  1.16k|    uint32_t preload;
 1583|  1.16k|    MAYBE_REFILL();
  ------------------
  |  | 1572|  1.16k|  if (SNAPPY_PREDICT_FALSE(ip >= ip_limit_min_maxtaglen_)) { \
  |  |  ------------------
  |  |  |  |   94|  1.16k|#define SNAPPY_PREDICT_FALSE(x) (__builtin_expect(x, 0))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (94:33): [True: 1.16k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  |  | 1573|  1.16k|    ip_ = ip;                                               \
  |  | 1574|  1.16k|    if (SNAPPY_PREDICT_FALSE(!RefillTag())) goto exit;       \
  |  |  ------------------
  |  |  |  |   94|  1.16k|#define SNAPPY_PREDICT_FALSE(x) (__builtin_expect(x, 0))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (94:33): [True: 71, False: 1.09k]
  |  |  |  |  ------------------
  |  |  ------------------
  |  | 1575|  1.16k|    ip = ip_;                                               \
  |  | 1576|  1.09k|    ResetLimit(ip);                                         \
  |  | 1577|  1.09k|  }                                                         \
  |  | 1578|  1.16k|  preload = static_cast<uint8_t>(*ip)
  ------------------
 1584|  12.9k|    for (;;) {
 1585|  12.9k|      {
 1586|  12.9k|        ptrdiff_t op_limit_min_slop;
 1587|  12.9k|        auto op_base = writer->GetBase(&op_limit_min_slop);
 1588|  12.9k|        if (op_base) {
  ------------------
  |  Branch (1588:13): [True: 12.7k, False: 231]
  ------------------
 1589|  12.7k|          auto res =
 1590|  12.7k|              DecompressBranchless(reinterpret_cast<const uint8_t*>(ip),
 1591|  12.7k|                                   reinterpret_cast<const uint8_t*>(ip_limit_),
 1592|  12.7k|                                   op - op_base, op_base, op_limit_min_slop);
 1593|  12.7k|          ip = reinterpret_cast<const char*>(res.first);
 1594|  12.7k|          op = op_base + res.second;
 1595|  12.7k|          MAYBE_REFILL();
  ------------------
  |  | 1572|  12.7k|  if (SNAPPY_PREDICT_FALSE(ip >= ip_limit_min_maxtaglen_)) { \
  |  |  ------------------
  |  |  |  |   94|  12.7k|#define SNAPPY_PREDICT_FALSE(x) (__builtin_expect(x, 0))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (94:33): [True: 457, False: 12.2k]
  |  |  |  |  ------------------
  |  |  ------------------
  |  | 1573|    457|    ip_ = ip;                                               \
  |  | 1574|    457|    if (SNAPPY_PREDICT_FALSE(!RefillTag())) goto exit;       \
  |  |  ------------------
  |  |  |  |   94|    457|#define SNAPPY_PREDICT_FALSE(x) (__builtin_expect(x, 0))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (94:33): [True: 0, False: 457]
  |  |  |  |  ------------------
  |  |  ------------------
  |  | 1575|    457|    ip = ip_;                                               \
  |  | 1576|    457|    ResetLimit(ip);                                         \
  |  | 1577|    457|  }                                                         \
  |  | 1578|  12.7k|  preload = static_cast<uint8_t>(*ip)
  ------------------
 1596|  12.7k|        }
 1597|  12.9k|      }
 1598|  12.9k|      const uint8_t c = static_cast<uint8_t>(preload);
 1599|  12.9k|      ip++;
 1600|       |
 1601|       |      // Ratio of iterations that have LITERAL vs non-LITERAL for different
 1602|       |      // inputs.
 1603|       |      //
 1604|       |      // input          LITERAL  NON_LITERAL
 1605|       |      // -----------------------------------
 1606|       |      // html|html4|cp   23%        77%
 1607|       |      // urls            36%        64%
 1608|       |      // jpg             47%        53%
 1609|       |      // pdf             19%        81%
 1610|       |      // txt[1-4]        25%        75%
 1611|       |      // pb              24%        76%
 1612|       |      // bin             24%        76%
 1613|  12.9k|      if (SNAPPY_PREDICT_FALSE((c & 0x3) == LITERAL)) {
  ------------------
  |  |   94|  12.9k|#define SNAPPY_PREDICT_FALSE(x) (__builtin_expect(x, 0))
  |  |  ------------------
  |  |  |  Branch (94:33): [True: 5.80k, False: 7.13k]
  |  |  ------------------
  ------------------
 1614|  5.80k|        size_t literal_length = (c >> 2) + 1u;
 1615|  5.80k|        if (writer->TryFastAppend(ip, ip_limit_ - ip, literal_length, &op)) {
  ------------------
  |  Branch (1615:13): [True: 2.29k, False: 3.50k]
  ------------------
 1616|  2.29k|          assert(literal_length < 61);
 1617|  2.29k|          ip += literal_length;
 1618|       |          // NOTE: There is no MAYBE_REFILL() here, as TryFastAppend()
 1619|       |          // will not return true unless there's already at least five spare
 1620|       |          // bytes in addition to the literal.
 1621|  2.29k|          preload = static_cast<uint8_t>(*ip);
 1622|  2.29k|          continue;
 1623|  2.29k|        }
 1624|  3.50k|        if (SNAPPY_PREDICT_FALSE(literal_length >= 61)) {
  ------------------
  |  |   94|  3.50k|#define SNAPPY_PREDICT_FALSE(x) (__builtin_expect(x, 0))
  |  |  ------------------
  |  |  |  Branch (94:33): [True: 2.52k, False: 977]
  |  |  ------------------
  ------------------
 1625|       |          // Long literal.
 1626|  2.52k|          const size_t literal_length_length = literal_length - 60;
 1627|  2.52k|          literal_length =
 1628|  2.52k|              ExtractLowBytes(LittleEndian::Load32(ip), literal_length_length) +
 1629|  2.52k|              1;
 1630|  2.52k|          ip += literal_length_length;
 1631|  2.52k|        }
 1632|       |
 1633|  3.50k|        size_t avail = ip_limit_ - ip;
 1634|  3.50k|        while (avail < literal_length) {
  ------------------
  |  Branch (1634:16): [True: 164, False: 3.34k]
  ------------------
 1635|    164|          if (!writer->Append(ip, avail, &op)) goto exit;
  ------------------
  |  Branch (1635:15): [True: 9, False: 155]
  ------------------
 1636|    155|          literal_length -= avail;
 1637|    155|          reader_->Skip(peeked_);
 1638|    155|          size_t n;
 1639|    155|          ip = reader_->Peek(&n);
 1640|    155|          avail = n;
 1641|    155|          peeked_ = avail;
 1642|    155|          if (avail == 0) goto exit;
  ------------------
  |  Branch (1642:15): [True: 155, False: 0]
  ------------------
 1643|      0|          ip_limit_ = ip + avail;
 1644|      0|          ResetLimit(ip);
 1645|      0|        }
 1646|  3.34k|        if (!writer->Append(ip, literal_length, &op)) goto exit;
  ------------------
  |  Branch (1646:13): [True: 42, False: 3.29k]
  ------------------
 1647|  3.29k|        ip += literal_length;
 1648|  3.29k|        MAYBE_REFILL();
  ------------------
  |  | 1572|  3.29k|  if (SNAPPY_PREDICT_FALSE(ip >= ip_limit_min_maxtaglen_)) { \
  |  |  ------------------
  |  |  |  |   94|  3.29k|#define SNAPPY_PREDICT_FALSE(x) (__builtin_expect(x, 0))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (94:33): [True: 186, False: 3.11k]
  |  |  |  |  ------------------
  |  |  ------------------
  |  | 1573|    186|    ip_ = ip;                                               \
  |  | 1574|    186|    if (SNAPPY_PREDICT_FALSE(!RefillTag())) goto exit;       \
  |  |  ------------------
  |  |  |  |   94|    186|#define SNAPPY_PREDICT_FALSE(x) (__builtin_expect(x, 0))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (94:33): [True: 50, False: 136]
  |  |  |  |  ------------------
  |  |  ------------------
  |  | 1575|    186|    ip = ip_;                                               \
  |  | 1576|    136|    ResetLimit(ip);                                         \
  |  | 1577|    136|  }                                                         \
  |  | 1578|  3.29k|  preload = static_cast<uint8_t>(*ip)
  ------------------
 1649|  7.13k|      } else {
 1650|  7.13k|        if (SNAPPY_PREDICT_FALSE((c & 3) == COPY_4_BYTE_OFFSET)) {
  ------------------
  |  |   94|  7.13k|#define SNAPPY_PREDICT_FALSE(x) (__builtin_expect(x, 0))
  |  |  ------------------
  |  |  |  Branch (94:33): [True: 1.39k, False: 5.73k]
  |  |  ------------------
  ------------------
 1651|  1.39k|          const size_t copy_offset = LittleEndian::Load32(ip);
 1652|  1.39k|          const size_t length = (c >> 2) + 1;
 1653|  1.39k|          ip += 4;
 1654|       |
 1655|  1.39k|          if (!writer->AppendFromSelf(copy_offset, length, &op)) goto exit;
  ------------------
  |  Branch (1655:15): [True: 244, False: 1.15k]
  ------------------
 1656|  5.73k|        } else {
 1657|  5.73k|          const ptrdiff_t entry = kLengthMinusOffset[c];
 1658|  5.73k|          preload = LittleEndian::Load32(ip);
 1659|  5.73k|          const uint32_t trailer = ExtractLowBytes(preload, c & 3);
 1660|  5.73k|          const uint32_t length = entry & 0xff;
 1661|  5.73k|          assert(length > 0);
 1662|       |
 1663|       |          // copy_offset/256 is encoded in bits 8..10.  By just fetching
 1664|       |          // those bits, we get copy_offset (since the bit-field starts at
 1665|       |          // bit 8).
 1666|  5.73k|          const uint32_t copy_offset = trailer - entry + length;
 1667|  5.73k|          if (!writer->AppendFromSelf(copy_offset, length, &op)) goto exit;
  ------------------
  |  Branch (1667:15): [True: 356, False: 5.38k]
  ------------------
 1668|       |
 1669|  5.38k|          ip += (c & 3);
 1670|       |          // By using the result of the previous load we reduce the critical
 1671|       |          // dependency chain of ip to 4 cycles.
 1672|  5.38k|          preload >>= (c & 3) * 8;
 1673|  5.38k|          if (ip < ip_limit_min_maxtaglen_) continue;
  ------------------
  |  Branch (1673:15): [True: 5.03k, False: 346]
  ------------------
 1674|  5.38k|        }
 1675|  2.75k|        MAYBE_REFILL();
  ------------------
  |  | 1572|  1.49k|  if (SNAPPY_PREDICT_FALSE(ip >= ip_limit_min_maxtaglen_)) { \
  |  |  ------------------
  |  |  |  |   94|  1.49k|#define SNAPPY_PREDICT_FALSE(x) (__builtin_expect(x, 0))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (94:33): [True: 431, False: 1.06k]
  |  |  |  |  ------------------
  |  |  ------------------
  |  | 1573|    431|    ip_ = ip;                                               \
  |  | 1574|    431|    if (SNAPPY_PREDICT_FALSE(!RefillTag())) goto exit;       \
  |  |  ------------------
  |  |  |  |   94|    431|#define SNAPPY_PREDICT_FALSE(x) (__builtin_expect(x, 0))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (94:33): [True: 238, False: 193]
  |  |  |  |  ------------------
  |  |  ------------------
  |  | 1575|    431|    ip = ip_;                                               \
  |  | 1576|    193|    ResetLimit(ip);                                         \
  |  | 1577|    193|  }                                                         \
  |  | 1578|  1.49k|  preload = static_cast<uint8_t>(*ip)
  ------------------
 1676|  2.75k|      }
 1677|  12.9k|    }
 1678|      0|#undef MAYBE_REFILL
 1679|  1.16k|  exit:
 1680|  1.16k|    writer->SetOutputPtr(op);
 1681|  1.16k|  }
_ZN6snappy17SnappyArrayWriter12GetOutputPtrEv:
 2169|  1.16k|  char* GetOutputPtr() { return op_; }
_ZN6snappy17SnappyArrayWriter7GetBaseEPl:
 2170|  12.9k|  char* GetBase(ptrdiff_t* op_limit_min_slop) {
 2171|  12.9k|    *op_limit_min_slop = op_limit_min_slop_ - base_;
 2172|  12.9k|    return base_;
 2173|  12.9k|  }
_ZN6snappy17SnappyArrayWriter13TryFastAppendEPKcmmPPc:
 2186|  5.80k|                            char** op_p) {
 2187|  5.80k|    char* op = *op_p;
 2188|  5.80k|    const size_t space_left = op_limit_ - op;
 2189|  5.80k|    if (len <= 16 && available >= 16 + kMaximumTagLength && space_left >= 16) {
  ------------------
  |  Branch (2189:9): [True: 3.14k, False: 2.65k]
  |  Branch (2189:22): [True: 2.56k, False: 577]
  |  Branch (2189:61): [True: 2.29k, False: 270]
  ------------------
 2190|       |      // Fast path, used for the majority (about 95%) of invocations.
 2191|  2.29k|      UnalignedCopy128(ip, op);
 2192|  2.29k|      *op_p = op + len;
 2193|  2.29k|      return true;
 2194|  3.50k|    } else {
 2195|  3.50k|      return false;
 2196|  3.50k|    }
 2197|  5.80k|  }
_ZN6snappy17SnappyArrayWriter6AppendEPKcmPPc:
 2176|  3.50k|  inline bool Append(const char* ip, size_t len, char** op_p) {
 2177|  3.50k|    char* op = *op_p;
 2178|  3.50k|    const size_t space_left = op_limit_ - op;
 2179|  3.50k|    if (space_left < len) return false;
  ------------------
  |  Branch (2179:9): [True: 51, False: 3.45k]
  ------------------
 2180|  3.45k|    std::memcpy(op, ip, len);
 2181|  3.45k|    *op_p = op + len;
 2182|  3.45k|    return true;
 2183|  3.50k|  }
_ZN6snappy17SnappyArrayWriter14AppendFromSelfEmmPPc:
 2200|  7.13k|  inline bool AppendFromSelf(size_t offset, size_t len, char** op_p) {
 2201|  7.13k|    assert(len > 0);
 2202|  7.13k|    char* const op = *op_p;
 2203|  7.13k|    assert(op >= base_);
 2204|  7.13k|    char* const op_end = op + len;
 2205|       |
 2206|       |    // Check if we try to append from before the start of the buffer.
 2207|  7.13k|    if (SNAPPY_PREDICT_FALSE(static_cast<size_t>(op - base_) < offset))
  ------------------
  |  |   94|  7.13k|#define SNAPPY_PREDICT_FALSE(x) (__builtin_expect(x, 0))
  |  |  ------------------
  |  |  |  Branch (94:33): [True: 445, False: 6.68k]
  |  |  ------------------
  ------------------
 2208|    445|      return false;
 2209|       |
 2210|  6.68k|    if (SNAPPY_PREDICT_FALSE((kSlopBytes < 64 && len > kSlopBytes) ||
  ------------------
  |  |   94|  32.7k|#define SNAPPY_PREDICT_FALSE(x) (__builtin_expect(x, 0))
  |  |  ------------------
  |  |  |  Branch (94:33): [True: 5.45k, False: 1.23k]
  |  |  |  Branch (94:51): [Folded - Ignored]
  |  |  |  Branch (94:51): [True: 0, False: 0]
  |  |  |  Branch (94:51): [True: 689, False: 6.00k]
  |  |  |  Branch (94:51): [True: 4.76k, False: 1.23k]
  |  |  ------------------
  ------------------
 2211|  6.68k|                            op >= op_limit_min_slop_ || offset < len)) {
 2212|  5.45k|      if (op_end > op_limit_ || offset == 0) return false;
  ------------------
  |  Branch (2212:11): [True: 27, False: 5.42k]
  |  Branch (2212:33): [True: 128, False: 5.29k]
  ------------------
 2213|  5.29k|      *op_p = IncrementalCopy(op - offset, op, op_end, op_limit_);
 2214|  5.29k|      return true;
 2215|  5.45k|    }
 2216|  1.23k|    std::memmove(op, op - offset, kSlopBytes);
 2217|  1.23k|    *op_p = op_end;
 2218|  1.23k|    return true;
 2219|  6.68k|  }
_ZN6snappy17SnappyArrayWriter12SetOutputPtrEPc:
 2174|  1.16k|  void SetOutputPtr(char* op) { op_ = op; }
_ZN6snappy17SnappyArrayWriter5FlushEv:
 2224|  1.16k|  inline void Flush() {}
_ZNK6snappy17SnappyArrayWriter11CheckLengthEv:
 2167|    331|  inline bool CheckLength() const { return op_ == op_limit_; }

LLVMFuzzerTestOneInput:
   40|  1.22k|extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
   41|  1.22k|  std::string input(reinterpret_cast<const char*>(data), size);
   42|       |
   43|       |  // Avoid self-crafted decompression bombs.
   44|  1.22k|  size_t uncompressed_size;
   45|  1.22k|  constexpr size_t kMaxUncompressedSize = 1 << 20;
   46|  1.22k|  bool get_uncompressed_length_succeeded = snappy::GetUncompressedLength(
   47|  1.22k|      input.data(), input.size(), &uncompressed_size);
   48|  1.22k|  if (!get_uncompressed_length_succeeded ||
  ------------------
  |  Branch (48:7): [True: 47, False: 1.18k]
  ------------------
   49|  1.22k|      (uncompressed_size > kMaxUncompressedSize)) {
  ------------------
  |  Branch (49:7): [True: 17, False: 1.16k]
  ------------------
   50|     64|    return 0;
   51|     64|  }
   52|       |
   53|  1.16k|  std::string uncompressed;
   54|       |  // The return value of snappy::Uncompress() is ignored because decompression
   55|       |  // will fail on invalid inputs.
   56|  1.16k|  snappy::Uncompress(input.data(), input.size(), &uncompressed);
   57|  1.16k|  return 0;
   58|  1.22k|}

