Prefetch the dictionary contents.

PiperOrigin-RevId: 987007178
diff --git a/c/enc/backward_references_inc_opt.h b/c/enc/backward_references_inc_opt.h
index 9e1ef64..d26c282 100644
--- a/c/enc/backward_references_inc_opt.h
+++ b/c/enc/backward_references_inc_opt.h
@@ -109,6 +109,10 @@
     sr.len_code_delta = 0;
     sr.distance = 0;
     sr.score = kMinScore;
+    if (ENABLE_COMPOUND_DICTIONARY) {
+      PrefetchCompoundDictionaryMatchOpt(&params->dictionary.compound,
+          ringbuffer, ringbuffer_mask, position);
+    }
     FN(FindLongestMatch)(privat, params->dictionary.contextual.dict[dict_id],
         ringbuffer, ringbuffer_mask, dist_cache, position, max_length,
         max_distance, dictionary_start + gap, params->dist.max_distance, &sr);
@@ -138,6 +142,10 @@
           dict_id = params->dictionary.contextual.context_map[
               BROTLI_CONTEXT(p1, p2, literal_context_lut)];
         }
+        if (ENABLE_COMPOUND_DICTIONARY) {
+          PrefetchCompoundDictionaryMatchOpt(&params->dictionary.compound,
+              ringbuffer, ringbuffer_mask, position + 1);
+        }
         FN(FindLongestMatch)(privat,
             params->dictionary.contextual.dict[dict_id],
             ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length,
diff --git a/c/enc/hash.h b/c/enc/hash.h
index 2e0b047..8df275a 100644
--- a/c/enc/hash.h
+++ b/c/enc/hash.h
@@ -747,6 +747,25 @@
   return total_found;
 }
 
+static BROTLI_INLINE void PrefetchCompoundDictionaryMatchOpt(
+    const CompoundDictionary* addon, const uint8_t* BROTLI_RESTRICT data,
+    const size_t ring_buffer_mask, const size_t cur_ix) {
+  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;
+  const uint64_t bytes = BROTLI_UNALIGNED_LOAD64LE(&data[cur_ix_masked]);
+  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;
+    const uint32_t key = (uint32_t)(h >> view->hash_shift);
+    const uint32_t slot = key & view->slot_mask;
+    const uint32_t head = view->heads[key];
+    /* Deliberately branchless - if head == 0xFFFF (no items), we'll prefetch
+     * some garbage address.  Prefetch can't fault, so this is safe.*/
+    PREFETCH_L1(&view->items[view->slot_offsets[slot] + head]);
+  }
+}
+
 static BROTLI_INLINE void FindCompoundDictionaryMatchOpt(
     const PreparedDictionaryView* self, const uint8_t* BROTLI_RESTRICT data,
     const size_t ring_buffer_mask, const int* BROTLI_RESTRICT distance_cache,