Commit b2347b8175 for aom

commit b2347b8175a5b7d62cf9189fc298475a0d0d495b
Author: Frank Galligan <fgalligan@google.com>
Date:   Fri Nov 6 11:48:17 2026 -0800

    av1: Optimize txb_init_levels and block_error_qm

    Improve AVX2 transform level initialization, QM block error gathering,
    HoG cache accumulation, and R-D candidate sorting:
    - Specialize av1_txb_init_levels_avx2 for each transform height with
      compile-time padded strides and inline trailing TX_PAD_BOTTOM zero
      stores, and fix unaligned 32-bit zero padding stores in SSE4.1/NEON.
    - Pack 8 QM weights into two 32-bit halves in load_qm_weights_avx2
      (vmovd + vpinsrd + vpmovzxbd) and share the squared coefficient
      calculation in av1_block_error_qm_avx2.
    - Accumulate cached HoG gradients in uint32_t before converting to
      float and skip the unit luma scale loop.
    - Simplify sort_rd to standard single-loop insertion sort.

    Benchmarking results (incremental vs prev CL / cumulative vs baseline):
    - Stock avifenc still-image (Default 1T): +0.00% / -18.41% encode time
    - Stock avifenc still-image (Default 8T): -0.57% / -14.63% encode time
    - 48-image multi-rate corpus (Full Suite 1T): +0.05% / -18.28% time
    - 48-image multi-rate corpus (Full Suite 8T): -0.92% / -15.05% time
    - Bit-exact output (1T and 8T)

    TAG=agy
    CONV=b929a630-a6cd-45a0-979c-1767c30178ee
    Change-Id: I13870f94b27033f5033e6d5336136e3c9b989da8

diff --git a/av1/encoder/arm/encodetxb_neon.c b/av1/encoder/arm/encodetxb_neon.c
index 45e117bdb8..1b5a656c96 100644
--- a/av1/encoder/arm/encodetxb_neon.c
+++ b/av1/encoder/arm/encodetxb_neon.c
@@ -12,6 +12,7 @@
 #include <arm_neon.h>
 #include <assert.h>
 #include <math.h>
+#include <string.h>

 #include "config/aom_config.h"

@@ -80,7 +81,7 @@ void av1_txb_init_levels_neon(const tran_low_t *const coeff, const int width,
         j += 16;
         cf += 16;
       } while (j < height);
-      *(int32_t *)(ls + height) = 0;
+      memset(ls + height, 0, sizeof(*levels) * TX_PAD_HOR);
       ls += stride;
       i += 1;
     } while (i < width);
diff --git a/av1/encoder/intra_mode_search_utils.h b/av1/encoder/intra_mode_search_utils.h
index c7f07dbdd5..d64cc8c831 100644
--- a/av1/encoder/intra_mode_search_utils.h
+++ b/av1/encoder/intra_mode_search_utils.h
@@ -442,24 +442,29 @@ static inline void generate_hog_using_gradient_cache(const MACROBLOCK *x,
                                                 plane * MAX_SB_SQUARE +
                                                 block_offset_in_grad_cache;

-  // Retrieve the cached gradient information and generate the histogram.
+  // Accumulate cached gradients in integers first to avoid per-pixel
+  // int-to-float conversions inside the inner loop.
+  uint32_t int_hist[HOG_BINS] = { 0 };
   for (int r = 1; r < rows - 1; ++r) {
+    const PixelLevelGradientInfo *const row_info = grad_info_blk + r * sb_width;
     for (int c = 1; c < cols - 1; ++c) {
-      const uint16_t abs_dx_abs_dy_sum =
-          grad_info_blk[r * sb_width + c].abs_dx_abs_dy_sum;
+      const uint16_t abs_dx_abs_dy_sum = row_info[c].abs_dx_abs_dy_sum;
       if (!abs_dx_abs_dy_sum) continue;
       total += abs_dx_abs_dy_sum;
-      const bool is_dx_zero = grad_info_blk[r * sb_width + c].is_dx_zero;
-      if (is_dx_zero) {
-        hist[0] += abs_dx_abs_dy_sum >> 1;
-        hist[HOG_BINS - 1] += abs_dx_abs_dy_sum >> 1;
+      if (row_info[c].is_dx_zero) {
+        const uint32_t half = abs_dx_abs_dy_sum >> 1;
+        int_hist[0] += half;
+        int_hist[HOG_BINS - 1] += half;
       } else {
-        const int8_t idx = grad_info_blk[r * sb_width + c].hist_bin_idx;
+        const int8_t idx = row_info[c].hist_bin_idx;
         assert(idx >= 0 && idx < HOG_BINS);
-        hist[idx] += abs_dx_abs_dy_sum;
+        int_hist[idx] += abs_dx_abs_dy_sum;
       }
     }
   }
+  for (int b = 0; b < HOG_BINS; ++b) {
+    hist[b] = (float)int_hist[b];
+  }
   normalize_hog(total, hist);
 }

@@ -489,8 +494,11 @@ static inline void collect_hog_data(const MACROBLOCK *x, BLOCK_SIZE bsize,
   }

   // Scale the hog so the luma and chroma are on the same scale
-  for (int b = 0; b < HOG_BINS; ++b) {
-    hog[b] *= (1 + ss_x) * (1 + ss_y);
+  if (ss_x | ss_y) {
+    const float scale = (float)((1 + ss_x) * (1 + ss_y));
+    for (int b = 0; b < HOG_BINS; ++b) {
+      hog[b] *= scale;
+    }
   }
 }

diff --git a/av1/encoder/tx_search.c b/av1/encoder/tx_search.c
index 05aef376cd..68505e483d 100644
--- a/av1/encoder/tx_search.c
+++ b/av1/encoder/tx_search.c
@@ -1067,27 +1067,17 @@ static const int mul_factors[5] = { 80, 80, 70, 50, 30 };       // scale 100

 // R-D costs are sorted in ascending order.
 static inline void sort_rd(int64_t rds[], int txk[], int len) {
-  int i, j, k;
-
-  for (i = 1; i <= len - 1; ++i) {
-    for (j = 0; j < i; ++j) {
-      if (rds[j] > rds[i]) {
-        int64_t temprd;
-        int tempi;
-
-        temprd = rds[i];
-        tempi = txk[i];
-
-        for (k = i; k > j; k--) {
-          rds[k] = rds[k - 1];
-          txk[k] = txk[k - 1];
-        }
-
-        rds[j] = temprd;
-        txk[j] = tempi;
-        break;
-      }
-    }
+  for (int i = 1; i < len; ++i) {
+    const int64_t temprd = rds[i];
+    const int tempi = txk[i];
+    int j = i;
+    while (j > 0 && rds[j - 1] > temprd) {
+      rds[j] = rds[j - 1];
+      txk[j] = txk[j - 1];
+      --j;
+    }
+    rds[j] = temprd;
+    txk[j] = tempi;
   }
 }

diff --git a/av1/encoder/x86/encodetxb_avx2.c b/av1/encoder/x86/encodetxb_avx2.c
index ce61df7ffa..9bc652fbe0 100644
--- a/av1/encoder/x86/encodetxb_avx2.c
+++ b/av1/encoder/x86/encodetxb_avx2.c
@@ -23,24 +23,21 @@

 void av1_txb_init_levels_avx2(const tran_low_t *const coeff, const int width,
                               const int height, uint8_t *const levels) {
-  const int stride = height + TX_PAD_HOR;
+  assert(TX_PAD_HOR == 4 && TX_PAD_BOTTOM == 4);
   const __m256i y_zeros = _mm256_setzero_si256();
+  const __m128i zero = _mm256_castsi256_si128(y_zeros);

-  // Zero bottom padding using up to five unrolled stores.
-  const int32_t bottom_len = sizeof(*levels) * (TX_PAD_BOTTOM * stride);
-  uint8_t *const bottom_buf_end = levels + (width + TX_PAD_BOTTOM) * stride;
-  const int num_stores = (bottom_len + 31) >> 5;
-  assert(num_stores >= 1 && num_stores <= 5);
-  yy_storeu_256(bottom_buf_end - 32, y_zeros);
-  if (num_stores > 1) yy_storeu_256(bottom_buf_end - 64, y_zeros);
-  if (num_stores > 2) yy_storeu_256(bottom_buf_end - 96, y_zeros);
-  if (num_stores > 3) yy_storeu_256(bottom_buf_end - 128, y_zeros);
-  if (num_stores > 4) yy_storeu_256(bottom_buf_end - 160, y_zeros);
-
-  int i = 0;
   uint8_t *ls = levels;
   const tran_low_t *cf = coeff;
+
+  // Specialize each transform height with its constant padded stride
+  // (height + TX_PAD_HOR) and zero the TX_PAD_BOTTOM (4) trailing rows directly
+  // after the loop.
   if (height == 4) {
+    assert(width > 0 && width % 4 == 0);
+    // Padded stride = 4 + 4 = 8; 4 rows of 4 coeffs + 4 zero-pad bytes per
+    // iter.
+    uint8_t *const ls_end = levels + width * 8;
     do {
       const __m256i c0 = yy_loadu_256(cf);
       const __m256i c1 = yy_loadu_256(cf + 8);
@@ -51,9 +48,13 @@ void av1_txb_init_levels_avx2(const tran_low_t *const coeff, const int width,
       yy_storeu_256(ls, res);
       ls += 32;
       cf += 16;
-      i += 4;
-    } while (i < width);
+    } while (ls < ls_end);
+    // Zero 4 bottom padding rows (4 * 8 = 32 bytes).
+    yy_storeu_256(ls, y_zeros);
   } else if (height == 8) {
+    assert(width > 0 && width % 4 == 0);
+    // Padded stride = 8 + 4 = 12; 4 rows per iteration (4 * 12 = 48 bytes).
+    uint8_t *const ls_end = levels + width * 12;
     do {
       const __m256i coeffA = yy_loadu_256(cf);
       const __m256i coeffB = yy_loadu_256(cf + 8);
@@ -68,19 +69,25 @@ void av1_txb_init_levels_avx2(const tran_low_t *const coeff, const int width,
       const __m256i res = _mm256_shuffle_epi32(res_, 0xd8);
       const __m128i res0 = _mm256_castsi256_si128(res);
       const __m128i res1 = _mm256_extracti128_si256(res, 1);
+
       xx_storel_64(ls, res0);
-      *(int32_t *)(ls + height) = 0;
-      xx_storel_64(ls + stride, _mm_srli_si128(res0, 8));
-      *(int32_t *)(ls + height + stride) = 0;
-      xx_storel_64(ls + stride * 2, res1);
-      *(int32_t *)(ls + height + stride * 2) = 0;
-      xx_storel_64(ls + stride * 3, _mm_srli_si128(res1, 8));
-      *(int32_t *)(ls + height + stride * 3) = 0;
+      xx_storel_32(ls + 8, zero);
+      xx_storel_64(ls + 12, _mm_srli_si128(res0, 8));
+      xx_storel_32(ls + 20, zero);
+      xx_storel_64(ls + 24, res1);
+      xx_storel_32(ls + 32, zero);
+      xx_storel_64(ls + 36, _mm_srli_si128(res1, 8));
+      xx_storel_32(ls + 44, zero);
       cf += 32;
-      ls += stride << 2;
-      i += 4;
-    } while (i < width);
+      ls += 48;
+    } while (ls < ls_end);
+    // Zero 4 bottom padding rows (4 * 12 = 48 bytes).
+    yy_storeu_256(ls, y_zeros);
+    xx_storeu_128(ls + 32, zero);
   } else if (height == 16) {
+    assert(width > 0 && width % 2 == 0);
+    // Padded stride = 16 + 4 = 20; 2 rows per iteration (2 * 20 = 40 bytes).
+    uint8_t *const ls_end = levels + width * 20;
     do {
       const __m256i coeffA = yy_loadu_256(cf);
       const __m256i coeffB = yy_loadu_256(cf + 8);
@@ -93,15 +100,22 @@ void av1_txb_init_levels_avx2(const tran_low_t *const coeff, const int width,
       const __m256i absABCD = _mm256_packs_epi16(absAB, absCD);
       const __m256i res_ = _mm256_permute4x64_epi64(absABCD, 0xd8);
       const __m256i res = _mm256_shuffle_epi32(res_, 0xd8);
+
       xx_storeu_128(ls, _mm256_castsi256_si128(res));
-      xx_storeu_128(ls + stride, _mm256_extracti128_si256(res, 1));
+      xx_storeu_128(ls + 20, _mm256_extracti128_si256(res, 1));
       cf += 32;
-      *(int32_t *)(ls + height) = 0;
-      *(int32_t *)(ls + stride + height) = 0;
-      ls += stride << 1;
-      i += 2;
-    } while (i < width);
+      xx_storel_32(ls + 16, zero);
+      xx_storel_32(ls + 36, zero);
+      ls += 40;
+    } while (ls < ls_end);
+    // Zero 4 bottom padding rows (4 * 20 = 80 bytes).
+    yy_storeu_256(ls, y_zeros);
+    yy_storeu_256(ls + 32, y_zeros);
+    xx_storeu_128(ls + 64, zero);
   } else {
+    assert(height == 32 && width > 0);
+    // Padded stride = 32 + 4 = 36; 1 row per iteration (36 bytes).
+    uint8_t *const ls_end = levels + width * 36;
     do {
       const __m256i coeffA = yy_loadu_256(cf);
       const __m256i coeffB = yy_loadu_256(cf + 8);
@@ -114,11 +128,17 @@ void av1_txb_init_levels_avx2(const tran_low_t *const coeff, const int width,
       const __m256i absABCD = _mm256_packs_epi16(absAB, absCD);
       const __m256i res_ = _mm256_permute4x64_epi64(absABCD, 0xd8);
       const __m256i res = _mm256_shuffle_epi32(res_, 0xd8);
+
       yy_storeu_256(ls, res);
       cf += 32;
-      *(int32_t *)(ls + height) = 0;
-      ls += stride;
-      i += 1;
-    } while (i < width);
+      xx_storel_32(ls + 32, zero);
+      ls += 36;
+    } while (ls < ls_end);
+    // Zero 4 bottom padding rows (4 * 36 = 144 bytes).
+    yy_storeu_256(ls, y_zeros);
+    yy_storeu_256(ls + 32, y_zeros);
+    yy_storeu_256(ls + 64, y_zeros);
+    yy_storeu_256(ls + 96, y_zeros);
+    xx_storeu_128(ls + 128, zero);
   }
 }
diff --git a/av1/encoder/x86/encodetxb_sse4.c b/av1/encoder/x86/encodetxb_sse4.c
index 081e8265b2..48f3a45c0d 100644
--- a/av1/encoder/x86/encodetxb_sse4.c
+++ b/av1/encoder/x86/encodetxb_sse4.c
@@ -76,7 +76,7 @@ void av1_txb_init_levels_sse4_1(const tran_low_t *const coeff, const int width,
         j += 16;
         cf += 16;
       } while (j < height);
-      *(int32_t *)(ls + height) = 0;
+      xx_storel_32(ls + height, zeros);
       ls += stride;
       i += 1;
     } while (i < width);
diff --git a/av1/encoder/x86/error_intrin_avx2.c b/av1/encoder/x86/error_intrin_avx2.c
index 6b514718d0..e5c8c0651a 100644
--- a/av1/encoder/x86/error_intrin_avx2.c
+++ b/av1/encoder/x86/error_intrin_avx2.c
@@ -210,6 +210,27 @@ int64_t av1_block_error_avx2(const tran_low_t *coeff, const tran_low_t *dqcoeff,
   return sse;
 }

+// Gather 8 quantization matrix weights indexed by scan_ptr[0..7] into two
+// 32-bit halves via _mm_cvtsi32_si128 + _mm_insert_epi32 and zero-extend to 8
+// 32-bit lanes with _mm256_cvtepu8_epi32 (preserving 32-bit x86 builds).
+static inline __m256i load_qm_weights_avx2(const qm_val_t *qmatrix,
+                                           const int16_t *scan_ptr) {
+  const uint32_t w01 =
+      (uint32_t)qmatrix[scan_ptr[0]] | ((uint32_t)qmatrix[scan_ptr[1]] << 8);
+  const uint32_t w23 = ((uint32_t)qmatrix[scan_ptr[2]] << 16) |
+                       ((uint32_t)qmatrix[scan_ptr[3]] << 24);
+  const uint32_t lo = w01 | w23;
+
+  const uint32_t w45 =
+      (uint32_t)qmatrix[scan_ptr[4]] | ((uint32_t)qmatrix[scan_ptr[5]] << 8);
+  const uint32_t w67 = ((uint32_t)qmatrix[scan_ptr[6]] << 16) |
+                       ((uint32_t)qmatrix[scan_ptr[7]] << 24);
+  const uint32_t hi = w45 | w67;
+
+  return _mm256_cvtepu8_epi32(
+      _mm_insert_epi32(_mm_cvtsi32_si128((int)lo), (int)hi, 1));
+}
+
 int64_t av1_block_error_qm_avx2(const tran_low_t *coeff,
                                 const tran_low_t *dqcoeff, intptr_t block_size,
                                 const qm_val_t *qmatrix, const int16_t *scan,
@@ -219,45 +240,37 @@ int64_t av1_block_error_qm_avx2(const tran_low_t *coeff,
   __m256i sse_reg = _mm256_setzero_si256();
   __m256i ssz_reg = _mm256_setzero_si256();
   const __m256i round_qm = _mm256_set1_epi64x(1 << (2 * AOM_QM_BITS - 1));
+  const int16_t *const scan_end = scan + block_size;

-  for (intptr_t i = 0; i < block_size; i += 8) {
+  for (; scan < scan_end; coeff += 8, dqcoeff += 8, scan += 8) {
     // Load 8 transform coefficients and dequantized coefficients.
-    const __m256i coeff_reg = _mm256_loadu_si256((const __m256i *)(coeff + i));
-    const __m256i dqcoeff_reg =
-        _mm256_loadu_si256((const __m256i *)(dqcoeff + i));
+    const __m256i coeff_reg = _mm256_loadu_si256((const __m256i *)coeff);
+    const __m256i dqcoeff_reg = _mm256_loadu_si256((const __m256i *)dqcoeff);
+    if (_mm256_testz_si256(dqcoeff_reg, dqcoeff_reg) &&
+        _mm256_testz_si256(coeff_reg, coeff_reg)) {
+      continue;
+    }

-    // When all 8 dequantized coefficients are zero, sse and ssz accumulate the
-    // same weighted squared coefficient energy.
+    // Compute weighted squared coefficient energy coeff^2 in 64-bit lanes.
+    const __m256i wt_reg = load_qm_weights_avx2(qmatrix, scan);
+    const __m256i cc = _mm256_mullo_epi32(coeff_reg, wt_reg);
+    const __m256i cc_hi = _mm256_srli_epi64(cc, 32);
+    const __m256i cc_lo_sq = _mm256_mul_epi32(cc, cc);
+    const __m256i cc_hi_sq = _mm256_mul_epi32(cc_hi, cc_hi);
+    const __m256i sq_lo = _mm256_srli_epi64(
+        _mm256_add_epi64(cc_lo_sq, round_qm), 2 * AOM_QM_BITS);
+    const __m256i sq_hi = _mm256_srli_epi64(
+        _mm256_add_epi64(cc_hi_sq, round_qm), 2 * AOM_QM_BITS);
+    const __m256i sq = _mm256_add_epi64(sq_lo, sq_hi);
+    ssz_reg = _mm256_add_epi64(ssz_reg, sq);
+
+    // When all 8 dequantized coefficients are zero, sse equals ssz for these 8
+    // lanes; otherwise compute weighted squared error (coeff - dqcoeff)^2.
     if (_mm256_testz_si256(dqcoeff_reg, dqcoeff_reg)) {
-      if (_mm256_testz_si256(coeff_reg, coeff_reg)) continue;
-
-      const __m256i wt_reg = _mm256_setr_epi32(
-          qmatrix[scan[i + 0]], qmatrix[scan[i + 1]], qmatrix[scan[i + 2]],
-          qmatrix[scan[i + 3]], qmatrix[scan[i + 4]], qmatrix[scan[i + 5]],
-          qmatrix[scan[i + 6]], qmatrix[scan[i + 7]]);
-      const __m256i cc = _mm256_mullo_epi32(coeff_reg, wt_reg);
-      const __m256i cc_hi = _mm256_srli_epi64(cc, 32);
-      const __m256i cc_lo_sq = _mm256_mul_epi32(cc, cc);
-      const __m256i cc_hi_sq = _mm256_mul_epi32(cc_hi, cc_hi);
-
-      const __m256i sq_lo = _mm256_srli_epi64(
-          _mm256_add_epi64(cc_lo_sq, round_qm), 2 * AOM_QM_BITS);
-      const __m256i sq_hi = _mm256_srli_epi64(
-          _mm256_add_epi64(cc_hi_sq, round_qm), 2 * AOM_QM_BITS);
-      const __m256i sq = _mm256_add_epi64(sq_lo, sq_hi);
-
       sse_reg = _mm256_add_epi64(sse_reg, sq);
-      ssz_reg = _mm256_add_epi64(ssz_reg, sq);
     } else {
-      const __m256i wt_reg = _mm256_setr_epi32(
-          qmatrix[scan[i + 0]], qmatrix[scan[i + 1]], qmatrix[scan[i + 2]],
-          qmatrix[scan[i + 3]], qmatrix[scan[i + 4]], qmatrix[scan[i + 5]],
-          qmatrix[scan[i + 6]], qmatrix[scan[i + 7]]);
       const __m256i diff = _mm256_sub_epi32(coeff_reg, dqcoeff_reg);
       const __m256i dd = _mm256_mullo_epi32(diff, wt_reg);
-      const __m256i cc = _mm256_mullo_epi32(coeff_reg, wt_reg);
-
-      // Compute weighted squared error (coeff - dqcoeff)^2 in 64-bit lanes.
       const __m256i dd_hi = _mm256_srli_epi64(dd, 32);
       const __m256i dd_lo_sq = _mm256_mul_epi32(dd, dd);
       const __m256i dd_hi_sq = _mm256_mul_epi32(dd_hi, dd_hi);
@@ -266,16 +279,6 @@ int64_t av1_block_error_qm_avx2(const tran_low_t *coeff,
       const __m256i err_hi = _mm256_srli_epi64(
           _mm256_add_epi64(dd_hi_sq, round_qm), 2 * AOM_QM_BITS);
       sse_reg = _mm256_add_epi64(sse_reg, _mm256_add_epi64(err_lo, err_hi));
-
-      // Compute weighted squared coefficient energy coeff^2 in 64-bit lanes.
-      const __m256i cc_hi = _mm256_srli_epi64(cc, 32);
-      const __m256i cc_lo_sq = _mm256_mul_epi32(cc, cc);
-      const __m256i cc_hi_sq = _mm256_mul_epi32(cc_hi, cc_hi);
-      const __m256i sq_lo = _mm256_srli_epi64(
-          _mm256_add_epi64(cc_lo_sq, round_qm), 2 * AOM_QM_BITS);
-      const __m256i sq_hi = _mm256_srli_epi64(
-          _mm256_add_epi64(cc_hi_sq, round_qm), 2 * AOM_QM_BITS);
-      ssz_reg = _mm256_add_epi64(ssz_reg, _mm256_add_epi64(sq_lo, sq_hi));
     }
   }

@@ -291,14 +294,16 @@ int64_t av1_block_error_qm_avx2(const tran_low_t *coeff,
   const __m128i ssz_reg128 = _mm_add_epi64(
       _mm256_castsi256_si128(ssz_reg), _mm256_extracti128_si256(ssz_reg, 1));

-  // Scale down for high bit-depth and store the results.
+  // Scale down for high bit-depth when bd > 8 and store the results.
   int64_t sse, sqcoeff;
   _mm_storel_epi64((__m128i *)&sse, sse_reg128);
   _mm_storel_epi64((__m128i *)&sqcoeff, ssz_reg128);
-  const int shift = 2 * (bd - 8);
-  const int rounding = (1 << shift) >> 1;
-  sse = (sse + rounding) >> shift;
-  sqcoeff = (sqcoeff + rounding) >> shift;
+  if (bd > 8) {
+    const int shift = 2 * (bd - 8);
+    const int rounding = (1 << shift) >> 1;
+    sse = (sse + rounding) >> shift;
+    sqcoeff = (sqcoeff + rounding) >> shift;
+  }

   *ssz = sqcoeff;
   return sse;
diff --git a/test/encodetxb_test.cc b/test/encodetxb_test.cc
index 2fd3efd2a7..cfa7467e92 100644
--- a/test/encodetxb_test.cc
+++ b/test/encodetxb_test.cc
@@ -223,16 +223,23 @@ void EncodeTxbInitLevelTest::RunTest(av1_txb_init_levels_func test_func,
   tran_low_t coeff[MAX_TX_SQUARE];

   uint8_t levels_buf[2][TX_PAD_2D];
+  alignas(4) uint8_t levels_unaligned_buf[TX_PAD_2D + 1];
   uint8_t *const levels0 = set_levels(levels_buf[0], height);
   uint8_t *const levels1 = set_levels(levels_buf[1], height);
+  uint8_t *const levels_unaligned =
+      set_levels(levels_unaligned_buf + 1, height);

   ACMRandom rnd(ACMRandom::DeterministicSeed());
   for (int i = 0; i < width * height; i++) {
     coeff[i] = rnd.Rand16Signed();
   }
+  const uint8_t canary = rnd.Rand8();
+  levels_unaligned_buf[0] = canary;
   for (int i = 0; i < TX_PAD_2D; i++) {
-    levels_buf[0][i] = rnd.Rand8();
-    levels_buf[1][i] = rnd.Rand8();
+    const uint8_t init_byte = rnd.Rand8();
+    levels_buf[0][i] = init_byte;
+    levels_buf[1][i] = init_byte;
+    levels_unaligned_buf[i + 1] = init_byte;
   }
   const int run_times = is_speed ? (width * height) * 10000 : 1;
   aom_usec_timer timer;
@@ -249,6 +256,9 @@ void EncodeTxbInitLevelTest::RunTest(av1_txb_init_levels_func test_func,
   if (is_speed) {
     printf("init %3dx%-3d:%7.2f/%7.2fns", width, height, t1, t2);
     printf("(%3.2f)\n", t1 / t2);
+  } else {
+    API_REGISTER_STATE_CHECK(test_func(coeff, width, height, levels_unaligned));
+    ASSERT_EQ(canary, levels_unaligned_buf[0]);
   }
   const int stride = width + TX_PAD_HOR;
   for (int r = 0; r < height + TX_PAD_VER; ++r) {
@@ -256,6 +266,11 @@ void EncodeTxbInitLevelTest::RunTest(av1_txb_init_levels_func test_func,
       ASSERT_EQ(levels_buf[0][c + r * stride], levels_buf[1][c + r * stride])
           << "[" << r << "," << c << "] " << run_times << width << "x"
           << height;
+      if (!is_speed) {
+        ASSERT_EQ(levels_buf[0][c + r * stride],
+                  levels_unaligned_buf[1 + c + r * stride])
+            << "unaligned [" << r << "," << c << "] " << width << "x" << height;
+      }
     }
   }
 }
diff --git a/test/error_block_test.cc b/test/error_block_test.cc
index 62856603a7..49cb2af327 100644
--- a/test/error_block_test.cc
+++ b/test/error_block_test.cc
@@ -75,10 +75,11 @@ int64_t BlockErrorQmWrapper(const tran_low_t *coeff, const tran_low_t *dqcoeff,
   static qm_val_t qmatrix[4096];
   static int16_t scan[4096];
   static const bool initialized = [&]() {
+    // Exercise full qm_val_t range [16, 242] (up to iwt_matrix_ref max) and a
+    // non-contiguous bijection within each 16-coefficient slice so every
+    // block_size prefix gathers permuted weights via scan_ptr[0..7].
     for (int i = 0; i < 4096; ++i) {
-      qmatrix[i] = static_cast<qm_val_t>(16 + ((i * 37) & 0x7f));
-      // Permute scan within each 16-element chunk to exercise non-identity
-      // gathered qmatrix indexing for all valid block sizes >= 16.
+      qmatrix[i] = static_cast<qm_val_t>(16 + ((i * 37) % 227));
       scan[i] = static_cast<int16_t>((i & ~15) | ((i * 5 + 3) & 15));
     }
     return true;