Add is_chroma_ref flag in MACROBLOCKD

is_chroma_reference() is called many times during the encoding and
decoding process. Adding the is_chroma_ref flag in MACROBLOCKD saves
such repeated computations, and makes the code cleaner.

Change-Id: Iab918b884a281aee3d026104df15c1ed0c0d8e55
diff --git a/av1/common/blockd.c b/av1/common/blockd.c
index 55bd052..24757d5 100644
--- a/av1/common/blockd.c
+++ b/av1/common/blockd.c
@@ -59,12 +59,7 @@
 void av1_reset_skip_context(MACROBLOCKD *xd, BLOCK_SIZE bsize,
                             const int num_planes) {
   assert(bsize < BLOCK_SIZES_ALL);
-  const int mi_row = xd->mi_row;
-  const int mi_col = xd->mi_col;
-  const int chroma_ref =
-      is_chroma_reference(mi_row, mi_col, bsize, xd->plane[1].subsampling_x,
-                          xd->plane[1].subsampling_y);
-  const int nplanes = 1 + (num_planes - 1) * chroma_ref;
+  const int nplanes = 1 + (num_planes - 1) * xd->is_chroma_ref;
   for (int i = 0; i < nplanes; i++) {
     struct macroblockd_plane *const pd = &xd->plane[i];
     const BLOCK_SIZE plane_bsize =
diff --git a/av1/common/blockd.h b/av1/common/blockd.h
index cc6f25d..c8e8bfc 100644
--- a/av1/common/blockd.h
+++ b/av1/common/blockd.h
@@ -508,6 +508,7 @@
 
   int mi_row;
   int mi_col;
+  int is_chroma_ref;
 
   /* pointers to reference frame scale factors */
   const struct scale_factors *block_ref_scale_factors[2];
diff --git a/av1/common/mvref_common.h b/av1/common/mvref_common.h
index f000d25..9871e21 100644
--- a/av1/common/mvref_common.h
+++ b/av1/common/mvref_common.h
@@ -302,15 +302,12 @@
 
   // Special case for sub 8x8 chroma cases, to prevent referring to chroma
   // pixels outside current tile.
-  for (int plane = 1; plane < av1_num_planes(cm); ++plane) {
-    const struct macroblockd_plane *const pd = &xd->plane[plane];
-    if (is_chroma_reference(mi_row, mi_col, bsize, pd->subsampling_x,
-                            pd->subsampling_y)) {
-      if (bw < 8 && pd->subsampling_x)
-        if (src_left_edge < tile_left_edge + 4 * SCALE_PX_TO_MV) return 0;
-      if (bh < 8 && pd->subsampling_y)
-        if (src_top_edge < tile_top_edge + 4 * SCALE_PX_TO_MV) return 0;
-    }
+  if (xd->is_chroma_ref && av1_num_planes(cm) > 1) {
+    const struct macroblockd_plane *const pd = &xd->plane[1];
+    if (bw < 8 && pd->subsampling_x)
+      if (src_left_edge < tile_left_edge + 4 * SCALE_PX_TO_MV) return 0;
+    if (bh < 8 && pd->subsampling_y)
+      if (src_top_edge < tile_top_edge + 4 * SCALE_PX_TO_MV) return 0;
   }
 
   // Is the bottom right within an already coded SB? Also consider additional
diff --git a/av1/common/onyxc_int.h b/av1/common/onyxc_int.h
index c567add6..cf70459 100644
--- a/av1/common/onyxc_int.h
+++ b/av1/common/onyxc_int.h
@@ -874,6 +874,7 @@
 
   const int chroma_ref = ((mi_row & 0x01) || !(bh & 0x01) || !ss_y) &&
                          ((mi_col & 0x01) || !(bw & 0x01) || !ss_x);
+  xd->is_chroma_ref = chroma_ref;
   if (chroma_ref) {
     // To help calculate the "above" and "left" chroma blocks, note that the
     // current block may cover multiple luma blocks (eg, if partitioned into
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index e345aba..9bd21bf 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -850,20 +850,15 @@
 }
 
 static AOM_INLINE void dec_build_inter_predictors_for_planes(
-    const AV1_COMMON *cm, MACROBLOCKD *xd, BLOCK_SIZE bsize, int mi_row,
-    int mi_col, int plane_from, int plane_to) {
-  int plane;
+    const AV1_COMMON *cm, MACROBLOCKD *xd, int mi_row, int mi_col,
+    int plane_from, int plane_to) {
   const int mi_x = mi_col * MI_SIZE;
   const int mi_y = mi_row * MI_SIZE;
-  for (plane = plane_from; plane <= plane_to; ++plane) {
+  for (int plane = plane_from; plane <= plane_to; ++plane) {
+    if (plane && !xd->is_chroma_ref) break;
     const struct macroblockd_plane *pd = &xd->plane[plane];
     const int bw = pd->width;
     const int bh = pd->height;
-
-    if (!is_chroma_reference(mi_row, mi_col, bsize, pd->subsampling_x,
-                             pd->subsampling_y))
-      continue;
-
     dec_build_inter_predictors(cm, xd, plane, xd->mi[0], 0, bw, bh, mi_x, mi_y);
   }
 }
@@ -873,7 +868,7 @@
                                                       int mi_row, int mi_col,
                                                       const BUFFER_SET *ctx,
                                                       BLOCK_SIZE bsize) {
-  dec_build_inter_predictors_for_planes(cm, xd, bsize, mi_row, mi_col, 0, 0);
+  dec_build_inter_predictors_for_planes(cm, xd, mi_row, mi_col, 0, 0);
 
   if (is_interintra_pred(xd->mi[0])) {
     BUFFER_SET default_ctx = { { xd->plane[0].dst.buf, NULL, NULL },
@@ -889,7 +884,7 @@
                                                        int mi_row, int mi_col,
                                                        const BUFFER_SET *ctx,
                                                        BLOCK_SIZE bsize) {
-  dec_build_inter_predictors_for_planes(cm, xd, bsize, mi_row, mi_col, 1,
+  dec_build_inter_predictors_for_planes(cm, xd, mi_row, mi_col, 1,
                                         MAX_MB_PLANE - 1);
 
   if (is_interintra_pred(xd->mi[0])) {
@@ -1155,10 +1150,7 @@
   const int num_planes = av1_num_planes(cm);
   MB_MODE_INFO *mbmi = xd->mi[0];
   CFL_CTX *const cfl = &xd->cfl;
-  const int mi_row = xd->mi_row;
-  const int mi_col = xd->mi_col;
-  cfl->is_chroma_reference = is_chroma_reference(
-      mi_row, mi_col, bsize, cfl->subsampling_x, cfl->subsampling_y);
+  cfl->is_chroma_reference = xd->is_chroma_ref;
 
   if (!is_inter_block(mbmi)) {
     int row, col;
@@ -1175,11 +1167,8 @@
     for (row = 0; row < max_blocks_high; row += mu_blocks_high) {
       for (col = 0; col < max_blocks_wide; col += mu_blocks_wide) {
         for (int plane = 0; plane < num_planes; ++plane) {
+          if (plane && !xd->is_chroma_ref) break;
           const struct macroblockd_plane *const pd = &xd->plane[plane];
-          if (!is_chroma_reference(mi_row, mi_col, bsize, pd->subsampling_x,
-                                   pd->subsampling_y))
-            continue;
-
           const TX_SIZE tx_size = av1_get_tx_size(plane, xd);
           const int stepr = tx_size_high_unit[tx_size];
           const int stepc = tx_size_wide_unit[tx_size];
@@ -1226,11 +1215,10 @@
       for (row = 0; row < max_blocks_high; row += mu_blocks_high) {
         for (col = 0; col < max_blocks_wide; col += mu_blocks_wide) {
           for (int plane = 0; plane < num_planes; ++plane) {
+            if (plane && !xd->is_chroma_ref) break;
             const struct macroblockd_plane *const pd = &xd->plane[plane];
             const int ss_x = pd->subsampling_x;
             const int ss_y = pd->subsampling_y;
-            if (!is_chroma_reference(mi_row, mi_col, bsize, ss_x, ss_y))
-              continue;
             const BLOCK_SIZE plane_bsize =
                 get_plane_block_size(bsize, ss_x, ss_y);
             const TX_SIZE max_tx_size =
@@ -1263,7 +1251,7 @@
     td->cfl_store_inter_block_visit(cm, xd);
   }
 
-  av1_visit_palette(pbi, xd, r, bsize, set_color_index_map_offset);
+  av1_visit_palette(pbi, xd, r, set_color_index_map_offset);
 }
 
 static AOM_INLINE void set_inter_tx_size(MB_MODE_INFO *mbmi, int stride_log2,
@@ -1414,7 +1402,7 @@
   MACROBLOCKD *const xd = &td->xd;
   decode_mbmi_block(pbi, xd, mi_row, mi_col, r, partition, bsize);
 
-  av1_visit_palette(pbi, xd, r, bsize, av1_decode_palette_tokens);
+  av1_visit_palette(pbi, xd, r, av1_decode_palette_tokens);
 
   AV1_COMMON *cm = &pbi->common;
   const int num_planes = av1_num_planes(cm);
diff --git a/av1/decoder/decodemv.c b/av1/decoder/decodemv.c
index 4ab7963..c363aa3 100644
--- a/av1/decoder/decodemv.c
+++ b/av1/decoder/decodemv.c
@@ -561,10 +561,7 @@
       read_palette_colors_y(xd, cm->seq_params.bit_depth, pmi, r);
     }
   }
-  if (num_planes > 1 && mbmi->uv_mode == UV_DC_PRED &&
-      is_chroma_reference(xd->mi_row, xd->mi_col, bsize,
-                          xd->plane[1].subsampling_x,
-                          xd->plane[1].subsampling_y)) {
+  if (num_planes > 1 && mbmi->uv_mode == UV_DC_PRED && xd->is_chroma_ref) {
     const int palette_uv_mode_ctx = (pmi->palette_size[0] > 0);
     const int modev = aom_read_symbol(
         r, xd->tile_ctx->palette_uv_mode_cdf[palette_uv_mode_ctx], 2, ACCT_STR);
@@ -794,9 +791,7 @@
           ? read_angle_delta(r, ec_ctx->angle_delta_cdf[mbmi->mode - V_PRED])
           : 0;
 
-  if (!cm->seq_params.monochrome &&
-      is_chroma_reference(mi_row, mi_col, bsize, xd->plane[1].subsampling_x,
-                          xd->plane[1].subsampling_y)) {
+  if (!cm->seq_params.monochrome && xd->is_chroma_ref) {
     xd->cfl.is_chroma_reference = 1;
     mbmi->uv_mode =
         read_intra_mode_uv(ec_ctx, r, is_cfl_allowed(xd), mbmi->mode);
@@ -1057,9 +1052,7 @@
       use_angle_delta && av1_is_directional_mode(mbmi->mode)
           ? read_angle_delta(r, ec_ctx->angle_delta_cdf[mbmi->mode - V_PRED])
           : 0;
-  const int has_chroma = is_chroma_reference(xd->mi_row, xd->mi_col, bsize,
-                                             xd->plane[1].subsampling_x,
-                                             xd->plane[1].subsampling_y);
+  const int has_chroma = xd->is_chroma_ref;
   xd->cfl.is_chroma_reference = has_chroma;
   if (!cm->seq_params.monochrome && has_chroma) {
     mbmi->uv_mode =
@@ -1478,9 +1471,7 @@
     }
   }
 
-  xd->cfl.is_chroma_reference =
-      is_chroma_reference(mi_row, mi_col, bsize, cm->seq_params.subsampling_x,
-                          cm->seq_params.subsampling_y);
+  xd->cfl.is_chroma_reference = xd->is_chroma_ref;
   xd->cfl.store_y = store_cfl_required(cm, xd);
 
 #if DEC_MISMATCH_DEBUG
diff --git a/av1/decoder/decoder.c b/av1/decoder/decoder.c
index 574b30c..acd1164 100644
--- a/av1/decoder/decoder.c
+++ b/av1/decoder/decoder.c
@@ -252,14 +252,11 @@
 }
 
 void av1_visit_palette(AV1Decoder *const pbi, MACROBLOCKD *const xd,
-                       aom_reader *r, BLOCK_SIZE bsize,
-                       palette_visitor_fn_t visit) {
+                       aom_reader *r, palette_visitor_fn_t visit) {
   if (!is_inter_block(xd->mi[0])) {
     for (int plane = 0; plane < AOMMIN(2, av1_num_planes(&pbi->common));
          ++plane) {
-      const struct macroblockd_plane *const pd = &xd->plane[plane];
-      if (is_chroma_reference(xd->mi_row, xd->mi_col, bsize, pd->subsampling_x,
-                              pd->subsampling_y)) {
+      if (plane == 0 || xd->is_chroma_ref) {
         if (xd->mi[0]->palette_mode_info.palette_size[plane])
           visit(xd, plane, r);
       } else {
diff --git a/av1/decoder/decoder.h b/av1/decoder/decoder.h
index 25f2ac5..08952e1 100644
--- a/av1/decoder/decoder.h
+++ b/av1/decoder/decoder.h
@@ -312,8 +312,7 @@
                                      aom_reader *r);
 
 void av1_visit_palette(AV1Decoder *const pbi, MACROBLOCKD *const xd,
-                       aom_reader *r, BLOCK_SIZE bsize,
-                       palette_visitor_fn_t visit);
+                       aom_reader *r, palette_visitor_fn_t visit);
 
 typedef void (*block_visitor_fn_t)(AV1Decoder *const pbi, ThreadData *const td,
                                    int mi_row, int mi_col, aom_reader *r,
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 49eec05..22be840 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -773,10 +773,8 @@
     }
   }
 
-  const int uv_dc_pred = num_planes > 1 && mbmi->uv_mode == UV_DC_PRED &&
-                         is_chroma_reference(xd->mi_row, xd->mi_col, bsize,
-                                             xd->plane[1].subsampling_x,
-                                             xd->plane[1].subsampling_y);
+  const int uv_dc_pred =
+      num_planes > 1 && mbmi->uv_mode == UV_DC_PRED && xd->is_chroma_ref;
   if (uv_dc_pred) {
     const int n = pmi->palette_size[1];
     const int palette_uv_mode_ctx = (pmi->palette_size[0] > 0);
@@ -999,10 +997,7 @@
   }
 
   // UV mode and UV angle delta.
-  if (!cm->seq_params.monochrome &&
-      is_chroma_reference(xd->mi_row, xd->mi_col, bsize,
-                          xd->plane[1].subsampling_x,
-                          xd->plane[1].subsampling_y)) {
+  if (!cm->seq_params.monochrome && xd->is_chroma_ref) {
     const UV_PREDICTION_MODE uv_mode = mbmi->uv_mode;
     write_intra_uv_mode(ec_ctx, uv_mode, mode, is_cfl_allowed(xd), w);
     if (uv_mode == UV_CFL_PRED)
@@ -1448,11 +1443,7 @@
     for (int row = 0; row < num_4x4_h; row += mu_blocks_high) {
       for (int col = 0; col < num_4x4_w; col += mu_blocks_wide) {
         for (int plane = 0; plane < num_planes; ++plane) {
-          const struct macroblockd_plane *const pd = &xd->plane[plane];
-          if (!is_chroma_reference(xd->mi_row, xd->mi_col, bsize,
-                                   pd->subsampling_x, pd->subsampling_y)) {
-            continue;
-          }
+          if (plane && !xd->is_chroma_ref) break;
           write_inter_txb_coeff(cm, x, mbmi, w, tok, tok_end, &token_stats, row,
                                 col, &block[plane], plane);
         }
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index 40eeb6a..4df5647 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -784,9 +784,7 @@
   mbmi->skip = 0;
   // Reset skip mode flag.
   mbmi->skip_mode = 0;
-  x->skip_chroma_rd =
-      !is_chroma_reference(mi_row, mi_col, bsize, xd->plane[1].subsampling_x,
-                           xd->plane[1].subsampling_y);
+  x->skip_chroma_rd = !xd->is_chroma_ref;
 
   if (is_cur_buf_hbd(xd)) {
     x->source_variance = av1_high_get_sby_perpixel_variance(
@@ -984,8 +982,7 @@
                                        const MB_MODE_INFO *const mbmi,
                                        const MB_MODE_INFO *above_mi,
                                        const MB_MODE_INFO *left_mi,
-                                       const int intraonly, const int mi_row,
-                                       const int mi_col) {
+                                       const int intraonly) {
   FRAME_CONTEXT *fc = xd->tile_ctx;
   const PREDICTION_MODE y_mode = mbmi->mode;
   (void)counts;
@@ -1034,10 +1031,7 @@
                2 * MAX_ANGLE_DELTA + 1);
   }
 
-  if (!is_chroma_reference(mi_row, mi_col, bsize,
-                           xd->plane[AOM_PLANE_U].subsampling_x,
-                           xd->plane[AOM_PLANE_U].subsampling_y))
-    return;
+  if (!xd->is_chroma_ref) return;
 
   const UV_PREDICTION_MODE uv_mode = mbmi->uv_mode;
   const CFL_ALLOWED_TYPE cfl_allowed = is_cfl_allowed(xd);
@@ -1086,8 +1080,8 @@
   }
 }
 
-static AOM_INLINE void update_stats(const AV1_COMMON *const cm, ThreadData *td,
-                                    int mi_row, int mi_col) {
+static AOM_INLINE void update_stats(const AV1_COMMON *const cm,
+                                    ThreadData *td) {
   MACROBLOCK *x = &td->mb;
   MACROBLOCKD *const xd = &x->e_mbd;
   const MB_MODE_INFO *const mbmi = xd->mi[0];
@@ -1118,8 +1112,8 @@
 #if CONFIG_ENTROPY_STATS
   // delta quant applies to both intra and inter
   const int super_block_upper_left =
-      ((mi_row & (cm->seq_params.mib_size - 1)) == 0) &&
-      ((mi_col & (cm->seq_params.mib_size - 1)) == 0);
+      ((xd->mi_row & (cm->seq_params.mib_size - 1)) == 0) &&
+      ((xd->mi_col & (cm->seq_params.mib_size - 1)) == 0);
   const DeltaQInfo *const delta_q_info = &cm->delta_q_info;
   if (delta_q_info->delta_q_present_flag &&
       (bsize != cm->seq_params.sb_size || !mbmi->skip) &&
@@ -1162,7 +1156,7 @@
 
   if (!is_inter_block(mbmi)) {
     sum_intra_stats(cm, td->counts, xd, mbmi, xd->above_mbmi, xd->left_mbmi,
-                    frame_is_intra_only(cm), mi_row, mi_col);
+                    frame_is_intra_only(cm));
   }
 
   if (av1_allow_intrabc(cm)) {
@@ -1654,9 +1648,7 @@
       }
     }
 
-    if (tile_data->allow_update_cdf) {
-      update_stats(&cpi->common, td, mi_row, mi_col);
-    }
+    if (tile_data->allow_update_cdf) update_stats(&cpi->common, td);
 
     // Gather obmc and warped motion count to update the probability.
     if ((!cpi->sf.inter_sf.disable_obmc &&
@@ -5977,9 +5969,7 @@
   const int mi_row = xd->mi_row;
   const int mi_col = xd->mi_col;
   if (!is_inter) {
-    xd->cfl.is_chroma_reference =
-        is_chroma_reference(mi_row, mi_col, bsize, cm->seq_params.subsampling_x,
-                            cm->seq_params.subsampling_y);
+    xd->cfl.is_chroma_reference = xd->is_chroma_ref;
     xd->cfl.store_y = store_cfl_required(cm, xd);
     mbmi->skip = 1;
     for (int plane = 0; plane < num_planes; ++plane) {
@@ -6126,11 +6116,8 @@
     set_txfm_ctxs(tx_size, xd->n4_w, xd->n4_h,
                   (mbmi->skip || seg_skip) && is_inter_block(mbmi), xd);
   }
-  CFL_CTX *const cfl = &xd->cfl;
-  if (is_inter_block(mbmi) &&
-      !is_chroma_reference(mi_row, mi_col, bsize, cfl->subsampling_x,
-                           cfl->subsampling_y) &&
-      is_cfl_allowed(xd)) {
+
+  if (is_inter_block(mbmi) && !xd->is_chroma_ref && is_cfl_allowed(xd)) {
     cfl_store_block(xd, mbmi->sb_type, mbmi->tx_size);
   }
 }
diff --git a/av1/encoder/encodemb.c b/av1/encoder/encodemb.c
index 8e5e5fe..1762492 100644
--- a/av1/encoder/encodemb.c
+++ b/av1/encoder/encodemb.c
@@ -622,16 +622,11 @@
                                cpi->optimize_seg_arr[mbmi->segment_id] };
   const AV1_COMMON *const cm = &cpi->common;
   const int num_planes = av1_num_planes(cm);
-  const int mi_row = xd->mi_row;
-  const int mi_col = xd->mi_col;
   for (int plane = 0; plane < num_planes; ++plane) {
     const struct macroblockd_plane *const pd = &xd->plane[plane];
     const int subsampling_x = pd->subsampling_x;
     const int subsampling_y = pd->subsampling_y;
-    if (plane && !is_chroma_reference(mi_row, mi_col, bsize, subsampling_x,
-                                      subsampling_y)) {
-      continue;
-    }
+    if (plane && !xd->is_chroma_ref) break;
     const BLOCK_SIZE plane_bsize =
         get_plane_block_size(bsize, subsampling_x, subsampling_y);
     assert(plane_bsize < BLOCK_SIZES_ALL);
@@ -794,14 +789,11 @@
                                   int enable_optimize_b) {
   assert(bsize < BLOCK_SIZES_ALL);
   const MACROBLOCKD *const xd = &x->e_mbd;
+  if (plane && !xd->is_chroma_ref) return;
+
   const struct macroblockd_plane *const pd = &xd->plane[plane];
   const int ss_x = pd->subsampling_x;
   const int ss_y = pd->subsampling_y;
-  if (plane &&
-      !is_chroma_reference(xd->mi_row, xd->mi_col, bsize, ss_x, ss_y)) {
-    return;
-  }
-
   ENTROPY_CONTEXT ta[MAX_MIB_SIZE] = { 0 };
   ENTROPY_CONTEXT tl[MAX_MIB_SIZE] = { 0 };
   struct encode_b_args arg = {
diff --git a/av1/encoder/encodetxb.c b/av1/encoder/encodetxb.c
index e0bcf04..2193112 100644
--- a/av1/encoder/encodetxb.c
+++ b/av1/encoder/encodetxb.c
@@ -665,15 +665,12 @@
   for (row = 0; row < max_blocks_high; row += mu_blocks_high) {
     for (col = 0; col < max_blocks_wide; col += mu_blocks_wide) {
       for (int plane = 0; plane < num_planes; ++plane) {
-        const struct macroblockd_plane *const pd = &xd->plane[plane];
-        if (!is_chroma_reference(xd->mi_row, xd->mi_col, bsize,
-                                 pd->subsampling_x, pd->subsampling_y))
-          continue;
+        if (plane && !xd->is_chroma_ref) break;
         const TX_SIZE tx_size = av1_get_tx_size(plane, xd);
         const int stepr = tx_size_high_unit[tx_size];
         const int stepc = tx_size_wide_unit[tx_size];
         const int step = stepr * stepc;
-
+        const struct macroblockd_plane *const pd = &xd->plane[plane];
         const int unit_height = ROUND_POWER_OF_TWO(
             AOMMIN(mu_blocks_high + row, max_blocks_high), pd->subsampling_y);
         const int unit_width = ROUND_POWER_OF_TWO(
@@ -2246,13 +2243,10 @@
   }
 
   for (int plane = 0; plane < num_planes; ++plane) {
+    if (plane && !xd->is_chroma_ref) break;
     const struct macroblockd_plane *const pd = &xd->plane[plane];
     const int ss_x = pd->subsampling_x;
     const int ss_y = pd->subsampling_y;
-    if (plane &&
-        !is_chroma_reference(xd->mi_row, xd->mi_col, bsize, ss_x, ss_y)) {
-      continue;
-    }
     const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, ss_x, ss_y);
     av1_foreach_transformed_block_in_plane(
         xd, plane_bsize, plane, av1_update_and_record_txb_context, &arg);
diff --git a/av1/encoder/intra_mode_search.c b/av1/encoder/intra_mode_search.c
index 07d61e5..f2b88b9 100644
--- a/av1/encoder/intra_mode_search.c
+++ b/av1/encoder/intra_mode_search.c
@@ -1205,11 +1205,7 @@
     return;
   }
 
-  const int mi_row = xd->mi_row;
-  const int mi_col = xd->mi_col;
-  xd->cfl.is_chroma_reference =
-      is_chroma_reference(mi_row, mi_col, bsize, cm->seq_params.subsampling_x,
-                          cm->seq_params.subsampling_y);
+  xd->cfl.is_chroma_reference = xd->is_chroma_ref;
   // Only store reconstructed luma when there's chroma RDO. When there's no
   // chroma RDO, the reconstructed luma will be stored in encode_superblock().
   xd->cfl.store_y = store_cfl_required_rdo(cm, x);
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index 617dbac..2585863 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -2644,14 +2644,10 @@
   // Initialize default mode evaluation params
   set_mode_eval_params(cpi, x, DEFAULT_EVAL);
 
-  const int mi_row = xd->mi_row;
-  const int mi_col = xd->mi_col;
   if (intra_yrd < best_rd) {
     // Only store reconstructed luma when there's chroma RDO. When there's no
     // chroma RDO, the reconstructed luma will be stored in encode_superblock().
-    xd->cfl.is_chroma_reference =
-        is_chroma_reference(mi_row, mi_col, bsize, cm->seq_params.subsampling_x,
-                            cm->seq_params.subsampling_y);
+    xd->cfl.is_chroma_reference = xd->is_chroma_ref;
     xd->cfl.store_y = store_cfl_required_rdo(cm, x);
     if (xd->cfl.store_y) {
       // Restore reconstructed luma values.
diff --git a/av1/encoder/reconinter_enc.c b/av1/encoder/reconinter_enc.c
index 8269d2d..393e7bf 100644
--- a/av1/encoder/reconinter_enc.c
+++ b/av1/encoder/reconinter_enc.c
@@ -174,11 +174,9 @@
                                              MACROBLOCKD *xd, int mi_row,
                                              int mi_col, const BUFFER_SET *ctx,
                                              BLOCK_SIZE bsize, int plane_idx) {
-  const struct macroblockd_plane *pd = &xd->plane[plane_idx];
-  if (!is_chroma_reference(mi_row, mi_col, bsize, pd->subsampling_x,
-                           pd->subsampling_y))
-    return;
+  if (plane_idx && !xd->is_chroma_ref) return;
 
+  const struct macroblockd_plane *pd = &xd->plane[plane_idx];
   const int mi_x = mi_col * MI_SIZE;
   const int mi_y = mi_row * MI_SIZE;
   build_inter_predictors(cm, xd, plane_idx, xd->mi[0], pd->width, pd->height,
diff --git a/av1/encoder/tokenize.c b/av1/encoder/tokenize.c
index af95f6d..c8fb128 100644
--- a/av1/encoder/tokenize.c
+++ b/av1/encoder/tokenize.c
@@ -199,12 +199,10 @@
   }
 
   for (int plane = 0; plane < num_planes; ++plane) {
+    if (plane && !xd->is_chroma_ref) break;
     const struct macroblockd_plane *const pd = &xd->plane[plane];
     const int ss_x = pd->subsampling_x;
     const int ss_y = pd->subsampling_y;
-    if (!is_chroma_reference(mi_row, mi_col, bsize, ss_x, ss_y)) {
-      continue;
-    }
     const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, ss_x, ss_y);
     assert(plane_bsize < BLOCK_SIZES_ALL);
     const int mi_width = mi_size_wide[plane_bsize];
diff --git a/test/intrabc_test.cc b/test/intrabc_test.cc
index 6ef0a50..c53595d 100644
--- a/test/intrabc_test.cc
+++ b/test/intrabc_test.cc
@@ -157,10 +157,13 @@
   memset(&cm, 0, sizeof(cm));
 
   for (const DvTestCase &dv_case : kDvCases) {
+    const int mi_row = xd.tile.mi_row_start + dv_case.mi_row_offset;
+    const int mi_col = xd.tile.mi_col_start + dv_case.mi_col_offset;
+    xd.is_chroma_ref = is_chroma_reference(mi_row, mi_col, dv_case.bsize,
+                                           xd.plane[1].subsampling_x,
+                                           xd.plane[1].subsampling_y);
     EXPECT_EQ(static_cast<int>(dv_case.valid),
-              av1_is_dv_valid(dv_case.dv, &cm, &xd,
-                              xd.tile.mi_row_start + dv_case.mi_row_offset,
-                              xd.tile.mi_col_start + dv_case.mi_col_offset,
+              av1_is_dv_valid(dv_case.dv, &cm, &xd, mi_row, mi_col,
                               dv_case.bsize, MAX_MIB_SIZE_LOG2));
   }
 }