Use a better best_len in the lazy search.

PiperOrigin-RevId: 988596790
diff --git a/c/enc/backward_references_opt_inc.h b/c/enc/backward_references_opt_inc.h
index b9a14eb..149b43a 100644
--- a/c/enc/backward_references_opt_inc.h
+++ b/c/enc/backward_references_opt_inc.h
@@ -132,8 +132,12 @@
       for (;; --max_length) {
         const score_t cost_diff_lazy = 175;
         HasherSearchResult sr2;
-        sr2.len = params->quality < MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH ?
-            BROTLI_MIN(size_t, sr.len - 1, max_length) : 0;
+        sr2.len =
+            params->quality < MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH
+                ? BROTLI_MIN(size_t, sr.len - 1, max_length)
+                : BROTLI_MIN(size_t,
+                             MinimumBetterLength(sr.score + cost_diff_lazy - 1),
+                             max_length);
         sr2.len_code_delta = 0;
         sr2.distance = 0;
         sr2.score = kMinScore;
@@ -206,6 +210,13 @@
           range_start = BROTLI_MIN(size_t, range_end, BROTLI_MAX(size_t,
               range_start, position + sr.len - (sr.distance << 2)));
         }
+        /* The next search is at position + sr.len (the one-ahead in the
+           prefetch helper covers only the cur_ix + 1 successor): prefetch its
+           dictionary heads[] line before the StoreRange loop. */
+        if (ENABLE_COMPOUND_DICTIONARY) {
+          PrefetchCompoundDictionaryHeadsOpt(&params->dictionary.compound,
+              ringbuffer, ringbuffer_mask, position + sr.len);
+        }
         FN(StoreRange)(privat, ringbuffer, ringbuffer_mask, range_start,
                        range_end);
       }
diff --git a/c/enc/hash.h b/c/enc/hash.h
index dc16d47..35addc8 100644
--- a/c/enc/hash.h
+++ b/c/enc/hash.h
@@ -126,6 +126,13 @@
       BROTLI_DISTANCE_BIT_PENALTY * Log2FloorNonZero(backward_reference_offset);
 }
 
+/* Returns the minimum length of a backward reference that will improve on the
+ provided score.  We conservatively assume that the match will be a last
+ distance match, the best case scenario for the next match.*/
+static BROTLI_INLINE size_t MinimumBetterLength(score_t score) {
+  return (score - (BROTLI_SCORE_BASE + 15)) / BROTLI_LITERAL_BYTE_SCORE;
+}
+
 static BROTLI_INLINE score_t BackwardReferenceScoreUsingLastDistance(
     size_t copy_length) {
   return BROTLI_LITERAL_BYTE_SCORE * (score_t)copy_length +
@@ -774,6 +781,36 @@
     PREFETCH_L1(chain);
     probes[d].chain = chain;
     probes[d].item = (head == 0xFFFF) ? 1 : 0;
+
+    /* One-ahead for the heads[] line of the next probe: the next search is
+       at cur_ix + 1 (the lazy search, or the next position after a miss),
+       whose hash covers bytes cur_ix+1.. -- the same 8-byte load shifted by
+       one byte (hash_mask spans at most 56 bits for this to be exact; a
+       mismatch would only waste the prefetch). The heads[key] load above
+       misses L1 ~94% of the time (mostly L3 fills). */
+    {
+      const uint64_t h1 =
+          ((bytes >> 8) & view->hash_mask) * kPreparedDictionaryHashMul64Long;
+      PREFETCH_L1(&view->heads[(uint32_t)(h1 >> view->hash_shift)]);
+    }
+  }
+}
+
+/* The heads[] half of PrefetchCompoundDictionaryMatchOpt: hash the position
+   and prefetch its heads[] line, with no dependent items[] load. Used at the
+   commit site, where the successor position is known but the probe state for
+   it would not survive the intervening StoreRange. */
+static BROTLI_INLINE void PrefetchCompoundDictionaryHeadsOpt(
+    const CompoundDictionary* addon, const uint8_t* BROTLI_RESTRICT data,
+    const size_t ring_buffer_mask, const size_t cur_ix) {
+  const uint64_t bytes =
+      BROTLI_UNALIGNED_LOAD64LE(&data[cur_ix & ring_buffer_mask]);
+  size_t d;
+  for (d = 0; d < addon->num_chunks; ++d) {
+    const PreparedDictionaryView* view = &addon->chunk_views[d];
+    const uint64_t h =
+        (bytes & view->hash_mask) * kPreparedDictionaryHashMul64Long;
+    PREFETCH_L1(&view->heads[(uint32_t)(h >> view->hash_shift)]);
   }
 }
 
diff --git a/c/enc/hash_longest_match_simd_opt_inc.h b/c/enc/hash_longest_match_simd_opt_inc.h
index df9aa66..6985a5d 100644
--- a/c/enc/hash_longest_match_simd_opt_inc.h
+++ b/c/enc/hash_longest_match_simd_opt_inc.h
@@ -156,7 +156,12 @@
   /* Don't accept a short copy from far away. */
   score_t min_score = out->score;
   score_t best_score = out->score;
-  size_t best_len = out->len;
+  /* If we're still searching the static dictionary, we have to do the full
+     search to determine if we should check the static dictionary. */
+  size_t best_len =
+      self->common_->dict_num_matches < (self->common_->dict_num_lookups >> 7)
+          ? out->len
+          : 0;
   size_t i;
   /* Precalculate the hash key and prefetch the bucket. */
   const uint32_t hash =
@@ -170,6 +175,9 @@
   out->len = 0;
   out->len_code_delta = 0;
 
+  if (best_len < 1) {
+    best_len = 1;
+  }
   /* Try last distance first. */
   for (i = 0; i < (size_t)self->num_last_distances_to_check_; ++i) {
     const size_t backward = (size_t)distance_cache[i];
@@ -186,7 +194,8 @@
       break;
     }
     if (prev_ix + best_len > ring_buffer_mask ||
-        data[cur_ix_masked + best_len] != data[prev_ix + best_len]) {
+        BrotliUnalignedRead16(&data[cur_ix_masked + best_len - 1]) !=
+            BrotliUnalignedRead16(&data[prev_ix + best_len - 1])) {
       continue;
     }
     {