Add params to brotli to manually enable or disable the SIMD hashers.

PiperOrigin-RevId: 959173169
diff --git a/c/common/platform.h b/c/common/platform.h
index 8080cbb..d4d4723 100644
--- a/c/common/platform.h
+++ b/c/common/platform.h
@@ -661,9 +661,11 @@
 
 /* The SIMD matchers are only faster at certain quality levels. */
 #if defined(_M_X64) && defined(BROTLI_TZCNT64)
+#define BROTLI_MAX_RECOMMENDED_SIMD_QUALITY 7
 #define BROTLI_MAX_SIMD_QUALITY 7
 #elif defined(BROTLI_TZCNT64)
-#define BROTLI_MAX_SIMD_QUALITY 6
+#define BROTLI_MAX_RECOMMENDED_SIMD_QUALITY 6
+#define BROTLI_MAX_SIMD_QUALITY 7
 #endif
 
 #if defined(_MSC_VER)
diff --git a/c/enc/encode.c b/c/enc/encode.c
index 305c231..0d424c3 100644
--- a/c/enc/encode.c
+++ b/c/enc/encode.c
@@ -113,6 +113,11 @@
       state->params.max_base64_regions = value;
       return BROTLI_TRUE;
 
+    case BROTLI_PARAM_SIMD_HASHER:
+      if (value > 2) return BROTLI_FALSE;
+      state->params.simd_hasher = (BrotliEncoderSimdHasher)value;
+      return BROTLI_TRUE;
+
     default: return BROTLI_FALSE;
   }
 }
@@ -702,6 +707,7 @@
   BrotliInitSharedEncoderDictionary(&params->dictionary);
   params->base64_mode = (int)BROTLI_DEFAULT_BASE64_MODE;
   params->max_base64_regions = BROTLI_DEFAULT_MAX_BASE64_REGIONS;
+  params->simd_hasher = BROTLI_DEFAULT_SIMD_HASHER;
   params->dist.distance_postfix_bits = 0;
   params->dist.num_direct_distance_codes = 0;
   params->dist.alphabet_size_max =
diff --git a/c/enc/params.h b/c/enc/params.h
index 01b1a41..b34eb4b 100644
--- a/c/enc/params.h
+++ b/c/enc/params.h
@@ -43,6 +43,7 @@
   SharedEncoderDictionary dictionary;
   int base64_mode;
   size_t max_base64_regions;
+  BrotliEncoderSimdHasher simd_hasher;
 } BrotliEncoderParams;
 
 #endif  /* BROTLI_ENC_PARAMS_H_ */
diff --git a/c/enc/quality.h b/c/enc/quality.h
index 45d67bf..2b399be 100644
--- a/c/enc/quality.h
+++ b/c/enc/quality.h
@@ -153,6 +153,22 @@
 
   Where "q" is quality, "h" is hasher type, "b" is bucket bits,
   "l" is source len. */
+
+#if defined(BROTLI_MAX_SIMD_QUALITY)
+static BROTLI_INLINE BROTLI_BOOL
+ShouldUseSimdHasher(const BrotliEncoderParams* params) {
+  if (params->simd_hasher == BROTLI_SIMD_HASHER_DISABLE) {
+    return BROTLI_FALSE;
+  }
+  int max_quality = BROTLI_MAX_RECOMMENDED_SIMD_QUALITY;
+
+  if (params->simd_hasher == BROTLI_SIMD_HASHER_ENABLE) {
+    max_quality = BROTLI_MAX_SIMD_QUALITY;
+  }
+  return TO_BROTLI_BOOL(params->quality <= max_quality);
+}
+#endif
+
 static BROTLI_INLINE void ChooseHasher(const BrotliEncoderParams* params,
                                        BrotliHasherParams* hparams) {
   if (params->quality > 9) {
@@ -165,7 +181,7 @@
     hparams->type = params->quality < 7 ? 40 : params->quality < 9 ? 41 : 42;
   } else if (params->size_hint >= (1 << 20) && params->lgwin >= 19) {
 #if defined(BROTLI_MAX_SIMD_QUALITY)
-    hparams->type = params->quality <= BROTLI_MAX_SIMD_QUALITY ? 68 : 6;
+    hparams->type = ShouldUseSimdHasher(params) ? 68 : 6;
 #else
     hparams->type = 6;
 #endif
@@ -177,7 +193,7 @@
     /* TODO(eustas): often previous setting (H6) is faster and denser; consider
                      adding an option to use it. */
 #if defined(BROTLI_MAX_SIMD_QUALITY)
-    hparams->type = params->quality <= BROTLI_MAX_SIMD_QUALITY ? 58 : 5;
+    hparams->type = ShouldUseSimdHasher(params) ? 58 : 5;
 #else
     hparams->type = 5;
 #endif
diff --git a/c/include/brotli/encode.h b/c/include/brotli/encode.h
index 6c568a0..076025e 100644
--- a/c/include/brotli/encode.h
+++ b/c/include/brotli/encode.h
@@ -70,6 +70,18 @@
 
 #define BROTLI_DEFAULT_MAX_BASE64_REGIONS 16
 
+/** Options for ::BROTLI_PARAM_SIMD_HASHER parameter. */
+typedef enum BrotliEncoderSimdHasher {
+  /** Use SIMD hasher when recommended for the quality level. */
+  BROTLI_SIMD_HASHER_DEFAULT = 0,
+  /** Use SIMD hasher when supported up to quality 7. */
+  BROTLI_SIMD_HASHER_ENABLE = 1,
+  /** Never use SIMD hasher. */
+  BROTLI_SIMD_HASHER_DISABLE = 2
+} BrotliEncoderSimdHasher;
+
+#define BROTLI_DEFAULT_SIMD_HASHER BROTLI_SIMD_HASHER_DEFAULT
+
 /** Default value for ::BROTLI_PARAM_QUALITY parameter. */
 #define BROTLI_DEFAULT_QUALITY 11
 /** Default value for ::BROTLI_PARAM_LGWIN parameter. */
@@ -242,7 +254,14 @@
    * Maximum number of Base64 regions to detect.
    * Default is 16.
    */
-  BROTLI_PARAM_MAX_BASE64_REGIONS = 11
+  BROTLI_PARAM_MAX_BASE64_REGIONS = 11,
+  /**
+   * SIMD hasher usage mode.
+   *
+   * Controls whether the encoder uses SIMD hashers.
+   * See ::BrotliEncoderSimdHasher for options.
+   */
+  BROTLI_PARAM_SIMD_HASHER = 12
 } BrotliEncoderParameter;
 
 /**
diff --git a/docs/encode.h.3 b/docs/encode.h.3
index 2151051..c24fb97 100644
--- a/docs/encode.h.3
+++ b/docs/encode.h.3
@@ -71,6 +71,10 @@
 .br
 .RI "\fIOptions to be used with \fBBrotliEncoderSetParameter\fP\&. \fP"
 .ti -1c
+.RI "typedef enum \fBBrotliEncoderSimdHasher\fP \fBBrotliEncoderSimdHasher\fP"
+.br
+.RI "\fIOptions for \fBBROTLI_PARAM_SIMD_HASHER\fP parameter\&. \fP"
+.ti -1c
 .RI "typedef struct BrotliEncoderStateStruct \fBBrotliEncoderState\fP"
 .br
 .RI "\fIOpaque structure that holds encoder state\&. \fP"
@@ -196,6 +200,10 @@
 
 .PP
 Options to be used with \fBBrotliEncoderSetParameter\fP\&. 
+.SS "typedef enum \fBBrotliEncoderSimdHasher\fP  \fBBrotliEncoderSimdHasher\fP"
+
+.PP
+Options for \fBBROTLI_PARAM_SIMD_HASHER\fP parameter\&. 
 .SS "typedef struct BrotliEncoderStateStruct \fBBrotliEncoderState\fP"
 
 .PP
@@ -351,6 +359,25 @@
 .TP
 \fB\fIBROTLI_PARAM_MAX_BASE64_REGIONS \fP\fP
 Maximum number of Base64 regions to detect\&. Default is 16\&. 
+.TP
+\fB\fIBROTLI_PARAM_SIMD_HASHER \fP\fP
+SIMD hasher usage mode\&. Controls whether the encoder uses SIMD hashers\&. See \fBBrotliEncoderSimdHasher\fP for options\&. 
+.SS "enum \fBBrotliEncoderSimdHasher\fP"
+
+.PP
+Options for \fBBROTLI_PARAM_SIMD_HASHER\fP parameter\&. 
+.PP
+\fBEnumerator\fP
+.in +1c
+.TP
+\fB\fIBROTLI_SIMD_HASHER_DEFAULT \fP\fP
+Use SIMD hasher when recommended for the quality level\&. 
+.TP
+\fB\fIBROTLI_SIMD_HASHER_ENABLE \fP\fP
+Use SIMD hasher when supported up to quality 7\&. 
+.TP
+\fB\fIBROTLI_SIMD_HASHER_DISABLE \fP\fP
+Never use SIMD hasher\&. 
 .SH "Function Documentation"
 .PP 
 .SS "\fBBROTLI_BOOL\fP BrotliEncoderAttachPreparedDictionary (\fBBrotliEncoderState\fP * state, const BrotliEncoderPreparedDictionary * dictionary)"