Optimize multiply_and_scale() by precomputation

multiply_and_scale() is called in nested loops. Precompute the
components of w (w1 and w2) and pass the components of w to
multiply_and_scale().

Bug: b:319140742
Bug: oss-fuzz:66474
Change-Id: I1ecf42dd4a7a552739136cbfc21f16aaba8f4523
(cherry picked from commit 9ae3ff78826cb7ed785ebe999acefc3426d1820f)
diff --git a/av1/encoder/pickrst.c b/av1/encoder/pickrst.c
index 6753c9e..369529a 100644
--- a/av1/encoder/pickrst.c
+++ b/av1/encoder/pickrst.c
@@ -1103,13 +1103,26 @@
   return (i >= wiener_halfwin1 ? wiener_win - 1 - i : i);
 }
 
-// Calculates x * w / WIENER_TAP_SCALE_FACTOR. The multiplication may overflow,
-// so we do the multiplication by components and combine it with the division.
-static INLINE int64_t multiply_and_scale(int64_t x, int32_t w) {
-  // Let w = w1 * WIENER_TAP_SCALE_FACTOR + w2
-  const int32_t w1 = w / WIENER_TAP_SCALE_FACTOR;
-  const int32_t w2 = w - w1 * WIENER_TAP_SCALE_FACTOR;
+// Splits each w[i] into smaller components w1[i] and w2[i] such that
+// w[i] = w1[i] * WIENER_TAP_SCALE_FACTOR + w2[i].
+static INLINE void split_wiener_filter_coefficients(int wiener_win,
+                                                    const int32_t *w,
+                                                    int32_t *w1, int32_t *w2) {
+  for (int i = 0; i < wiener_win; i++) {
+    w1[i] = w[i] / WIENER_TAP_SCALE_FACTOR;
+    w2[i] = w[i] - w1[i] * WIENER_TAP_SCALE_FACTOR;
+    assert(w[i] == w1[i] * WIENER_TAP_SCALE_FACTOR + w2[i]);
+  }
+}
+
+// Calculates x * w / WIENER_TAP_SCALE_FACTOR, where
+// w = w1 * WIENER_TAP_SCALE_FACTOR + w2.
+//
+// The multiplication x * w may overflow, so we multiply x by the components of
+// w (w1 and w2) and combine the multiplication with the division.
+static INLINE int64_t multiply_and_scale(int64_t x, int32_t w1, int32_t w2) {
   // Let y = x * w / WIENER_TAP_SCALE_FACTOR
+  //       = x * (w1 * WIENER_TAP_SCALE_FACTOR + w2) / WIENER_TAP_SCALE_FACTOR
   const int64_t y = x * w1 + x * w2 / WIENER_TAP_SCALE_FACTOR;
   return y;
 }
@@ -1190,6 +1203,7 @@
   int i, j;
   int64_t S[WIENER_WIN];
   int64_t A[WIENER_HALFWIN1], B[WIENER_HALFWIN1 * WIENER_HALFWIN1];
+  int32_t b1[WIENER_WIN], b2[WIENER_WIN];
   const int wiener_win2 = wiener_win * wiener_win;
   const int wiener_halfwin1 = (wiener_win >> 1) + 1;
   memset(A, 0, sizeof(A));
@@ -1200,6 +1214,7 @@
       A[jj] += Mc[i][j] * b[i] / WIENER_TAP_SCALE_FACTOR;
     }
   }
+  split_wiener_filter_coefficients(wiener_win, b, b1, b2);
 
   for (i = 0; i < wiener_win; i++) {
     for (j = 0; j < wiener_win; j++) {
@@ -1217,7 +1232,8 @@
           // multiplication with the last division.
           const int64_t x = Hc[j * wiener_win + i][k * wiener_win2 + l] * b[i] /
                             WIENER_TAP_SCALE_FACTOR;
-          B[ll * wiener_halfwin1 + kk] += multiply_and_scale(x, b[j]);
+          // b[j] = b1[j] * WIENER_TAP_SCALE_FACTOR + b2[j]
+          B[ll * wiener_halfwin1 + kk] += multiply_and_scale(x, b1[j], b2[j]);
         }
       }
     }
@@ -1257,6 +1273,7 @@
   int i, j;
   int64_t S[WIENER_WIN];
   int64_t A[WIENER_HALFWIN1], B[WIENER_HALFWIN1 * WIENER_HALFWIN1];
+  int32_t a1[WIENER_WIN], a2[WIENER_WIN];
   const int wiener_win2 = wiener_win * wiener_win;
   const int wiener_halfwin1 = (wiener_win >> 1) + 1;
   memset(A, 0, sizeof(A));
@@ -1267,6 +1284,7 @@
       A[ii] += Mc[i][j] * a[j] / WIENER_TAP_SCALE_FACTOR;
     }
   }
+  split_wiener_filter_coefficients(wiener_win, a, a1, a2);
 
   for (i = 0; i < wiener_win; i++) {
     const int ii = wrap_index(i, wiener_win);
@@ -1284,7 +1302,8 @@
           // multiplication with the last division.
           const int64_t x = Hc[i * wiener_win + j][k * wiener_win2 + l] * a[k] /
                             WIENER_TAP_SCALE_FACTOR;
-          B[jj * wiener_halfwin1 + ii] += multiply_and_scale(x, a[l]);
+          // a[l] = a1[l] * WIENER_TAP_SCALE_FACTOR + a2[l]
+          B[jj * wiener_halfwin1 + ii] += multiply_and_scale(x, a1[l], a2[l]);
         }
       }
     }