Further work on ext-comp-refs for ref frame coding

(1) Work with var-refs to remove redundant bits in ref frame
    coding;
(2) Add a new uni-directional compound reference pair:
    (LAST_FRAME, LAST3_FRAME);
(3) Redesign the contexts for encoding uni-directional reference frame
    pairs;
(4) Use aom_entropy_optimizer to collect stats for all the default
    probability setups related to the coding of reference frames.

Compared against the baseline (default enabled tools excluding ext-tx
and global-motion for encoder speed concern) with one-sided-compound,
the coding gain of ext-comp-refs + var-refs - one-sided-compound is:

lowres: avg_psnr -0.385%; ovr_psnr -0.378% ssim -0.344%
midres: avg_psnr -0.466%; ovr_psnr -0.447% ssim -0.513%

AWCY - High Latency:
   PSNR | PSNR Cb | PSNR Cr | PSNR HVS |    SSIM | MS SSIM | CIEDE 2000
-0.2758 | -0.1526 | -0.0965 |  -0.2581 | -0.2492 | -0.2534 |    -0.2118

AWCY - Low Latency:
   PSNR | PSNR Cb | PSNR Cr | PSNR HVS |    SSIM | MS SSIM | CIEDE 2000
-1.0467 | -1.4500 | -0.9732 |  -0.9928 | -1.0407 | -1.0180 |    -1.0049

Compared against the baseline (default enabled tools excluding ext-tx
and global-motion for encoder speed concern) without
one-sided-compound, the coding gain of
ext-comp-refs + var-refs - one-sided-compound is:

lowres: avg_psnr -0.875%; ovr_psnr -0.877% ssim -0.895%
midres: avg_psnr -0.824%; ovr_psnr -0.802% ssim -0.843%

Change-Id: I8de774c9a74c20632ea93ccb0c17779fa94431cb
diff --git a/av1/common/blockd.h b/av1/common/blockd.h
index 6bf892a..bfdf48b 100644
--- a/av1/common/blockd.h
+++ b/av1/common/blockd.h
@@ -518,6 +518,7 @@
 static INLINE MV_REFERENCE_FRAME comp_ref0(int ref_idx) {
   static const MV_REFERENCE_FRAME lut[] = {
     LAST_FRAME,    // LAST_LAST2_FRAMES,
+    LAST_FRAME,    // LAST_LAST3_FRAMES,
     LAST_FRAME,    // LAST_GOLDEN_FRAMES,
     BWDREF_FRAME,  // BWDREF_ALTREF_FRAMES,
   };
@@ -528,6 +529,7 @@
 static INLINE MV_REFERENCE_FRAME comp_ref1(int ref_idx) {
   static const MV_REFERENCE_FRAME lut[] = {
     LAST2_FRAME,   // LAST_LAST2_FRAMES,
+    LAST3_FRAME,   // LAST_LAST3_FRAMES,
     GOLDEN_FRAME,  // LAST_GOLDEN_FRAMES,
     ALTREF_FRAME,  // BWDREF_ALTREF_FRAMES,
   };
@@ -621,8 +623,6 @@
   YV12_BUFFER_CONFIG *buf;
   struct scale_factors sf;
 #if CONFIG_VAR_REFS
-  // TODO(zoeliu): To evaluate whether "is_valid" is needed or the use of it can
-  // be simply replaced by checking the "idx".
   int is_valid;
 #endif  // CONFIG_VAR_REFS
 } RefBuffer;
diff --git a/av1/common/entropymode.c b/av1/common/entropymode.c
index bc88555..5c0ea7b 100644
--- a/av1/common/entropymode.c
+++ b/av1/common/entropymode.c
@@ -1040,44 +1040,94 @@
 #endif
 
 static const aom_prob default_comp_inter_p[COMP_INTER_CONTEXTS] = {
-  216, 170, 131, 92, 42,
+#if !CONFIG_EXT_COMP_REFS
+  216, 170, 131, 92, 42
+#else   // CONFIG_EXT_COMP_REFS
+  206, 182, 117, 104, 32
+#endif  // !CONFIG_EXT_COMP_REFS
 };
+
 #if CONFIG_NEW_MULTISYMBOL
-static const aom_cdf_prob default_comp_inter_cdf[COMP_INTER_CONTEXTS][CDF_SIZE(
-    2)] = { { AOM_ICDF(216 * 128), AOM_ICDF(32768), 0 },
-            { AOM_ICDF(170 * 128), AOM_ICDF(32768), 0 },
-            { AOM_ICDF(131 * 128), AOM_ICDF(32768), 0 },
-            { AOM_ICDF(92 * 128), AOM_ICDF(32768), 0 },
-            { AOM_ICDF(42 * 128), AOM_ICDF(32768), 0 } };
-#endif
+static const aom_cdf_prob
+    default_comp_inter_cdf[COMP_INTER_CONTEXTS][CDF_SIZE(2)] = {
+#if !CONFIG_EXT_COMP_REFS
+      { AOM_ICDF(216 * 128), AOM_ICDF(32768), 0 },
+      { AOM_ICDF(170 * 128), AOM_ICDF(32768), 0 },
+      { AOM_ICDF(131 * 128), AOM_ICDF(32768), 0 },
+      { AOM_ICDF(92 * 128), AOM_ICDF(32768), 0 },
+      { AOM_ICDF(42 * 128), AOM_ICDF(32768), 0 }
+#else   // CONFIG_EXT_COMP_REFS
+      { AOM_ICDF(206 * 128), AOM_ICDF(32768), 0 },
+      { AOM_ICDF(182 * 128), AOM_ICDF(32768), 0 },
+      { AOM_ICDF(117 * 128), AOM_ICDF(32768), 0 },
+      { AOM_ICDF(104 * 128), AOM_ICDF(32768), 0 },
+      { AOM_ICDF(32 * 128), AOM_ICDF(32768), 0 }
+#endif  // !CONFIG_EXT_COMP_REFS
+    };
+#endif  // CONFIG_NEW_MULTISYMBOL
 
 #if CONFIG_EXT_COMP_REFS
 static const aom_prob default_comp_ref_type_p[COMP_REF_TYPE_CONTEXTS] = {
-  30, 75, 120, 170, 230
+  8, 20, 78, 91, 194
 };
-
 static const aom_prob
     default_uni_comp_ref_p[UNI_COMP_REF_CONTEXTS][UNIDIR_COMP_REFS - 1] = {
-      { 30, 20 }, { 75, 70 }, { 130, 130 }, { 165, 165 }, { 215, 220 }
+      { 88, 30, 28 }, { 218, 97, 105 }, { 254, 180, 196 }
     };
+
+#if CONFIG_NEW_MULTISYMBOL
+static const aom_cdf_prob
+    default_comp_ref_type_cdf[COMP_REF_TYPE_CONTEXTS][CDF_SIZE(2)] = {
+      { AOM_ICDF(8 * 128), AOM_ICDF(32768), 0 },
+      { AOM_ICDF(20 * 128), AOM_ICDF(32768), 0 },
+      { AOM_ICDF(78 * 128), AOM_ICDF(32768), 0 },
+      { AOM_ICDF(91 * 128), AOM_ICDF(32768), 0 },
+      { AOM_ICDF(194 * 128), AOM_ICDF(32768), 0 }
+    };
+static const aom_cdf_prob
+    default_uni_comp_ref_cdf[UNI_COMP_REF_CONTEXTS][UNIDIR_COMP_REFS - 1]
+                            [CDF_SIZE(2)] = {
+                              { { AOM_ICDF(88 * 128), AOM_ICDF(32768), 0 },
+                                { AOM_ICDF(30 * 128), AOM_ICDF(32768), 0 },
+                                { AOM_ICDF(28 * 128), AOM_ICDF(32768), 0 } },
+                              { { AOM_ICDF(218 * 128), AOM_ICDF(32768), 0 },
+                                { AOM_ICDF(97 * 128), AOM_ICDF(32768), 0 },
+                                { AOM_ICDF(105 * 128), AOM_ICDF(32768), 0 } },
+                              { { AOM_ICDF(254 * 128), AOM_ICDF(32768), 0 },
+                                { AOM_ICDF(180 * 128), AOM_ICDF(32768), 0 },
+                                { AOM_ICDF(196 * 128), AOM_ICDF(32768), 0 } }
+                            };
+#endif  // CONFIG_NEW_MULTISYMBOL
 #endif  // CONFIG_EXT_COMP_REFS
 
 #if CONFIG_EXT_REFS
 static const aom_prob default_comp_ref_p[REF_CONTEXTS][FWD_REFS - 1] = {
-  // TODO(zoeliu): To adjust the initial prob values.
+#if !CONFIG_EXT_COMP_REFS
   { 33, 16, 16 },
   { 77, 74, 74 },
   { 142, 142, 142 },
   { 172, 170, 170 },
   { 238, 247, 247 }
+#else   // CONFIG_EXT_COMP_REFS
+  { 21, 7, 5 },
+  { 68, 20, 16 },
+  { 128, 56, 36 },
+  { 197, 111, 139 },
+  { 238, 131, 136 }
+#endif  // !CONFIG_EXT_COMP_REFS
 };
 static const aom_prob default_comp_bwdref_p[REF_CONTEXTS][BWD_REFS - 1] = {
+#if !CONFIG_EXT_COMP_REFS
   { 16 }, { 74 }, { 142 }, { 170 }, { 247 }
+#else   // CONFIG_EXT_COMP_REFS
+  { 7 }, { 56 }, { 29 }, { 230 }, { 220 }
+#endif  // CONFIG_EXT_COMP_REFS
 };
+
 #if CONFIG_NEW_MULTISYMBOL
 static const aom_cdf_prob
     default_comp_ref_cdf[REF_CONTEXTS][FWD_REFS - 1][CDF_SIZE(2)] = {
-      // TODO(zoeliu): To adjust the initial prob values.
+#if !CONFIG_EXT_COMP_REFS
       { { AOM_ICDF(33 * 128), AOM_ICDF(32768), 0 },
         { AOM_ICDF(16 * 128), AOM_ICDF(32768), 0 },
         { AOM_ICDF(16 * 128), AOM_ICDF(32768), 0 } },
@@ -1093,17 +1143,42 @@
       { { AOM_ICDF(238 * 128), AOM_ICDF(32768), 0 },
         { AOM_ICDF(247 * 128), AOM_ICDF(32768), 0 },
         { AOM_ICDF(247 * 128), AOM_ICDF(32768), 0 } }
+#else   // CONFIG_EXT_COMP_REFS
+      { { AOM_ICDF(21 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(7 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(5 * 128), AOM_ICDF(32768), 0 } },
+      { { AOM_ICDF(68 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(20 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(16 * 128), AOM_ICDF(32768), 0 } },
+      { { AOM_ICDF(128 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(56 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(36 * 128), AOM_ICDF(32768), 0 } },
+      { { AOM_ICDF(197 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(111 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(139 * 128), AOM_ICDF(32768), 0 } },
+      { { AOM_ICDF(238 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(131 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(136 * 128), AOM_ICDF(32768), 0 } }
+#endif  // !CONFIG_EXT_COMP_REFS
     };
 static const aom_cdf_prob
     default_comp_bwdref_cdf[REF_CONTEXTS][BWD_REFS - 1][CDF_SIZE(2)] = {
+#if !CONFIG_EXT_COMP_REFS
       { { AOM_ICDF(16 * 128), AOM_ICDF(32768), 0 } },
       { { AOM_ICDF(74 * 128), AOM_ICDF(32768), 0 } },
       { { AOM_ICDF(142 * 128), AOM_ICDF(32768), 0 } },
       { { AOM_ICDF(170 * 128), AOM_ICDF(32768), 0 } },
       { { AOM_ICDF(247 * 128), AOM_ICDF(32768), 0 } }
+#else   // CONFIG_EXT_COMP_REFS
+      { { AOM_ICDF(7 * 128), AOM_ICDF(32768), 0 } },
+      { { AOM_ICDF(56 * 128), AOM_ICDF(32768), 0 } },
+      { { AOM_ICDF(29 * 128), AOM_ICDF(32768), 0 } },
+      { { AOM_ICDF(230 * 128), AOM_ICDF(32768), 0 } },
+      { { AOM_ICDF(220 * 128), AOM_ICDF(32768), 0 } }
+#endif  // !CONFIG_EXT_COMP_REFS
     };
 #endif  // CONFIG_NEW_MULTISYMBOL
-#else
+#else   // !CONFIG_EXT_REFS
 static const aom_prob default_comp_ref_p[REF_CONTEXTS][COMP_REFS - 1] = {
   { 43 }, { 100 }, { 137 }, { 212 }, { 229 },
 };
@@ -1121,19 +1196,29 @@
 
 static const aom_prob default_single_ref_p[REF_CONTEXTS][SINGLE_REFS - 1] = {
 #if CONFIG_EXT_REFS
+#if !CONFIG_EXT_COMP_REFS
   { 33, 16, 16, 16, 16 },
   { 77, 74, 74, 74, 74 },
   { 142, 142, 142, 142, 142 },
   { 172, 170, 170, 170, 170 },
   { 238, 247, 247, 247, 247 }
-#else
+#else   // CONFIG_EXT_COMP_REFS
+  { 36, 2, 28, 58, 9 },
+  { 64, 22, 60, 122, 40 },
+  { 153, 69, 126, 179, 71 },
+  { 128, 174, 189, 216, 101 },
+  { 233, 252, 228, 246, 200 }
+#endif  // !CONFIG_EXT_COMP_REFS
+#else   // !CONFIG_EXT_REFS
   { 31, 25 }, { 72, 80 }, { 147, 148 }, { 197, 191 }, { 235, 247 },
 #endif  // CONFIG_EXT_REFS
 };
+
 #if CONFIG_NEW_MULTISYMBOL
 static const aom_cdf_prob
     default_single_ref_cdf[REF_CONTEXTS][SINGLE_REFS - 1][CDF_SIZE(2)] = {
 #if CONFIG_EXT_REFS
+#if !CONFIG_EXT_COMP_REFS
       { { AOM_ICDF(33 * 128), AOM_ICDF(32768), 0 },
         { AOM_ICDF(16 * 128), AOM_ICDF(32768), 0 },
         { AOM_ICDF(16 * 128), AOM_ICDF(32768), 0 },
@@ -1159,7 +1244,34 @@
         { AOM_ICDF(247 * 128), AOM_ICDF(32768), 0 },
         { AOM_ICDF(247 * 128), AOM_ICDF(32768), 0 },
         { AOM_ICDF(247 * 128), AOM_ICDF(32768), 0 } }
-#else
+#else   // CONFIG_EXT_COMP_REFS
+      { { AOM_ICDF(36 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(2 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(28 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(58 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(9 * 128), AOM_ICDF(32768), 0 } },
+      { { AOM_ICDF(64 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(22 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(60 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(122 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(40 * 128), AOM_ICDF(32768), 0 } },
+      { { AOM_ICDF(153 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(69 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(126 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(179 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(71 * 128), AOM_ICDF(32768), 0 } },
+      { { AOM_ICDF(128 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(174 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(189 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(216 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(101 * 128), AOM_ICDF(32768), 0 } },
+      { { AOM_ICDF(233 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(252 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(228 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(246 * 128), AOM_ICDF(32768), 0 },
+        { AOM_ICDF(200 * 128), AOM_ICDF(32768), 0 } }
+#endif  // !CONFIG_EXT_COMP_REFS
+#else   // CONFIG_EXT_REFS
       { { AOM_ICDF(31 * 128), AOM_ICDF(32768), 0 },
         { AOM_ICDF(25 * 128), AOM_ICDF(32768), 0 } },
       { { AOM_ICDF(72 * 128), AOM_ICDF(32768), 0 },
@@ -1172,7 +1284,7 @@
         { AOM_ICDF(247 * 128), AOM_ICDF(32768), 0 } }
 #endif  // CONFIG_EXT_REFS
     };
-#endif
+#endif  // CONFIG_NEW_MULTISYMBOL
 
 #if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
 // TODO(zoeliu): Default values to be further adjusted based on the collected
@@ -4560,6 +4672,10 @@
 #if CONFIG_EXT_COMP_REFS
   av1_copy(fc->comp_ref_type_prob, default_comp_ref_type_p);
   av1_copy(fc->uni_comp_ref_prob, default_uni_comp_ref_p);
+#if CONFIG_NEW_MULTISYMBOL
+  av1_copy(fc->comp_ref_type_cdf, default_comp_ref_type_cdf);
+  av1_copy(fc->uni_comp_ref_cdf, default_uni_comp_ref_cdf);
+#endif  // CONFIG_NEW_MULTISYMBOL
 #endif  // CONFIG_EXT_COMP_REFS
   av1_copy(fc->comp_ref_prob, default_comp_ref_p);
 #if CONFIG_NEW_MULTISYMBOL
diff --git a/av1/common/entropymode.h b/av1/common/entropymode.h
index 18d4aa2..5036ac0 100644
--- a/av1/common/entropymode.h
+++ b/av1/common/entropymode.h
@@ -248,6 +248,11 @@
 #if CONFIG_EXT_COMP_REFS
   aom_prob comp_ref_type_prob[COMP_REF_TYPE_CONTEXTS];
   aom_prob uni_comp_ref_prob[UNI_COMP_REF_CONTEXTS][UNIDIR_COMP_REFS - 1];
+#if CONFIG_NEW_MULTISYMBOL
+  aom_cdf_prob comp_ref_type_cdf[COMP_REF_TYPE_CONTEXTS][CDF_SIZE(2)];
+  aom_cdf_prob uni_comp_ref_cdf[UNI_COMP_REF_CONTEXTS][UNIDIR_COMP_REFS - 1]
+                               [CDF_SIZE(2)];
+#endif  // CONFIG_NEW_MULTISYMBOL
 #endif  // CONFIG_EXT_COMP_REFS
   aom_prob single_ref_prob[REF_CONTEXTS][SINGLE_REFS - 1];
 #if CONFIG_EXT_REFS
diff --git a/av1/common/enums.h b/av1/common/enums.h
index 1b59ce0..bd1ba7c 100644
--- a/av1/common/enums.h
+++ b/av1/common/enums.h
@@ -532,7 +532,7 @@
 
 #if CONFIG_EXT_COMP_REFS
 #define COMP_REF_TYPE_CONTEXTS 5
-#define UNI_COMP_REF_CONTEXTS 5
+#define UNI_COMP_REF_CONTEXTS 3
 #endif  // CONFIG_EXT_COMP_REFS
 
 #if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
@@ -577,6 +577,7 @@
 #if CONFIG_EXT_COMP_REFS
 typedef enum {
   LAST_LAST2_FRAMES,     // { LAST_FRAME, LAST2_FRAME }
+  LAST_LAST3_FRAMES,     // { LAST_FRAME, LAST3_FRAME }
   LAST_GOLDEN_FRAMES,    // { LAST_FRAME, GOLDEN_FRAME }
   BWDREF_ALTREF_FRAMES,  // { BWDREF_FRAME, ALTREF_FRAME }
   UNIDIR_COMP_REFS
diff --git a/av1/common/mvref_common.h b/av1/common/mvref_common.h
index acba436..63318f4 100644
--- a/av1/common/mvref_common.h
+++ b/av1/common/mvref_common.h
@@ -289,8 +289,8 @@
 
   // TODO(zoeliu): Temporarily disable uni-directional comp refs
 #if CONFIG_EXT_COMP_REFS
-  , { LAST_FRAME, LAST2_FRAME }, { LAST_FRAME, GOLDEN_FRAME },
-  { BWDREF_FRAME, ALTREF_FRAME }
+  , { LAST_FRAME, LAST2_FRAME }, { LAST_FRAME, LAST3_FRAME },
+  { LAST_FRAME, GOLDEN_FRAME }, { BWDREF_FRAME, ALTREF_FRAME }
 #endif  // CONFIG_EXT_COMP_REFS
 #else  // !CONFIG_EXT_REFS
   { LAST_FRAME, ALTREF_FRAME }, { GOLDEN_FRAME, ALTREF_FRAME }
diff --git a/av1/common/onyxc_int.h b/av1/common/onyxc_int.h
index 6133edf..61574dd 100644
--- a/av1/common/onyxc_int.h
+++ b/av1/common/onyxc_int.h
@@ -522,6 +522,8 @@
 
 #define L_OR_L2(cm) (LAST_IS_VALID(cm) || LAST2_IS_VALID(cm))
 #define L_AND_L2(cm) (LAST_IS_VALID(cm) && LAST2_IS_VALID(cm))
+#define L_AND_L3(cm) (LAST_IS_VALID(cm) && LAST3_IS_VALID(cm))
+#define L_AND_G(cm) (LAST_IS_VALID(cm) && GOLDEN_IS_VALID(cm))
 
 #define L3_OR_G(cm) (LAST3_IS_VALID(cm) || GOLDEN_IS_VALID(cm))
 #define L3_AND_G(cm) (LAST3_IS_VALID(cm) && GOLDEN_IS_VALID(cm))
diff --git a/av1/common/pred_common.c b/av1/common/pred_common.c
index 01e7f41..4b98a8c 100644
--- a/av1/common/pred_common.c
+++ b/av1/common/pred_common.c
@@ -263,6 +263,9 @@
 #define IS_BACKWARD_REF_FRAME(ref_frame) ((ref_frame) == cm->comp_fixed_ref)
 #endif  // CONFIG_EXT_REFS
 
+#define CHECK_GOLDEN_OR_LAST3(ref_frame) \
+  (((ref_frame) == GOLDEN_FRAME) || ((ref_frame) == LAST3_FRAME))
+
 int av1_get_reference_mode_context(const AV1_COMMON *cm,
                                    const MACROBLOCKD *xd) {
   int ctx;
@@ -313,16 +316,15 @@
 #if CONFIG_EXT_COMP_REFS
 #define CHECK_BWDREF_OR_ALTREF(ref_frame) \
   ((ref_frame) == BWDREF_FRAME || (ref_frame) == ALTREF_FRAME)
-int av1_get_comp_reference_type_context(const AV1_COMMON *cm,
-                                        const MACROBLOCKD *xd) {
+// TODO(zoeliu): To try on the design of 3 contexts, instead of 5:
+//               COMP_REF_TYPE_CONTEXTS = 3
+int av1_get_comp_reference_type_context(const MACROBLOCKD *xd) {
   int pred_context;
   const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
   const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
   const int above_in_image = xd->up_available;
   const int left_in_image = xd->left_available;
 
-  (void)cm;
-
   if (above_in_image && left_in_image) {  // both edges available
     const int above_intra = !is_inter_block(above_mbmi);
     const int left_intra = !is_inter_block(left_mbmi);
@@ -388,197 +390,165 @@
 }
 
 // Returns a context number for the given MB prediction signal
-// Signal the uni-directional compound reference frame pair as
-// either (BWDREF, ALTREF), or (LAST, LAST2)/(LAST, GOLDEN),
+//
+// Signal the uni-directional compound reference frame pair as either
+// (BWDREF, ALTREF), or (LAST, LAST2) / (LAST, LAST3) / (LAST, GOLDEN),
 // conditioning on the pair is known as uni-directional.
-int av1_get_pred_context_uni_comp_ref_p(const AV1_COMMON *cm,
-                                        const MACROBLOCKD *xd) {
+//
+// 3 contexts: Voting is used to compare the count of forward references with
+//             that of backward references from the spatial neighbors.
+int av1_get_pred_context_uni_comp_ref_p(const MACROBLOCKD *xd) {
   int pred_context;
   const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
   const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
   const int above_in_image = xd->up_available;
   const int left_in_image = xd->left_available;
 
-  (void)cm;
+  // Count of forward references (L, L2, L3, or G)
+  int frf_count = 0;
+  // Count of backward references (B or A)
+  int brf_count = 0;
 
-  if (above_in_image && left_in_image) {  // both edges available
-    const int above_intra = !is_inter_block(above_mbmi);
-    const int left_intra = !is_inter_block(left_mbmi);
-
-    if (above_intra && left_intra) {  // intra/intra
-      pred_context = 2;
-    } else if (above_intra || left_intra) {  // intra/inter
-      const MB_MODE_INFO *inter_mbmi = above_intra ? left_mbmi : above_mbmi;
-
-      if (!has_second_ref(inter_mbmi)) {  // single pred
-        pred_context =
-            1 + 2 * (!CHECK_BWDREF_OR_ALTREF(inter_mbmi->ref_frame[0]));
-      } else {                              // comp pred
-        if (has_uni_comp_refs(inter_mbmi))  // comp unidir
-          pred_context = 4 * (inter_mbmi->ref_frame[0] != BWDREF_FRAME);
-        else  // comp_bidir
-          pred_context = 2;
-      }
-    } else {  // inter/inter
-      const int a_sg = !has_second_ref(above_mbmi);
-      const int l_sg = !has_second_ref(left_mbmi);
-      const MV_REFERENCE_FRAME frfa = above_mbmi->ref_frame[0];
-      const MV_REFERENCE_FRAME frfl = left_mbmi->ref_frame[0];
-
-      if (CHECK_BWDREF_OR_ALTREF(frfa) && CHECK_BWDREF_OR_ALTREF(frfl)) {
-        pred_context = 0;
-      } else if (a_sg && l_sg) {  // single/single
-        pred_context = 2 + (!CHECK_BWDREF_OR_ALTREF(frfa) &&
-                            !CHECK_BWDREF_OR_ALTREF(frfl));
-      } else if (l_sg || a_sg) {  // single/comp
-        const MV_REFERENCE_FRAME frfc = a_sg ? frfl : frfa;
-        const MV_REFERENCE_FRAME rfs = a_sg ? frfa : frfl;
-        const int uni_rfc =
-            a_sg ? has_uni_comp_refs(left_mbmi) : has_uni_comp_refs(above_mbmi);
-
-        if (uni_rfc && (frfc == BWDREF_FRAME))
-          pred_context = 1;
-        else if (uni_rfc && (frfc == LAST_FRAME))
-          pred_context = 3 + (!CHECK_BWDREF_OR_ALTREF(rfs));
-        else if (CHECK_BWDREF_OR_ALTREF(rfs))
-          pred_context = 2;
-        else
-          pred_context = 3;
-      } else {  // comp/comp
-        const int a_uni_rfc = has_uni_comp_refs(above_mbmi);
-        const int l_uni_rfc = has_uni_comp_refs(left_mbmi);
-
-        if (a_uni_rfc && l_uni_rfc)
-          pred_context = 2 + 2 * (frfa != BWDREF_FRAME && frfl != BWDREF_FRAME);
-        else if (a_uni_rfc || l_uni_rfc)
-          pred_context = 1 + 2 * (frfa != BWDREF_FRAME && frfl != BWDREF_FRAME);
-        else
-          pred_context = 2;
-      }
+  if (above_in_image && is_inter_block(above_mbmi)) {
+    if (above_mbmi->ref_frame[0] <= GOLDEN_FRAME)
+      ++frf_count;
+    else
+      ++brf_count;
+    if (has_second_ref(above_mbmi)) {
+      if (above_mbmi->ref_frame[1] <= GOLDEN_FRAME)
+        ++frf_count;
+      else
+        ++brf_count;
     }
-  } else if (above_in_image || left_in_image) {  // one edge available
-    const MB_MODE_INFO *edge_mbmi = above_in_image ? above_mbmi : left_mbmi;
-
-    if (!is_inter_block(edge_mbmi)) {  // intra
-      pred_context = 2;
-    } else {                             // inter
-      if (!has_second_ref(edge_mbmi)) {  // single pred
-        pred_context =
-            1 + 2 * (!CHECK_BWDREF_OR_ALTREF(edge_mbmi->ref_frame[0]));
-      } else {                             // comp pred
-        if (has_uni_comp_refs(edge_mbmi))  // comp unidir
-          pred_context = 4 * (edge_mbmi->ref_frame[0] != BWDREF_FRAME);
-        else  // comp bidir
-          pred_context = 2;
-      }
-    }
-  } else {  // no edges available
-    pred_context = 2;
   }
 
+  if (left_in_image && is_inter_block(left_mbmi)) {
+    if (left_mbmi->ref_frame[0] <= GOLDEN_FRAME)
+      ++frf_count;
+    else
+      ++brf_count;
+    if (has_second_ref(left_mbmi)) {
+      if (left_mbmi->ref_frame[1] <= GOLDEN_FRAME)
+        ++frf_count;
+      else
+        ++brf_count;
+    }
+  }
+
+  pred_context =
+      (frf_count == brf_count) ? 1 : ((frf_count < brf_count) ? 0 : 2);
+
   assert(pred_context >= 0 && pred_context < UNI_COMP_REF_CONTEXTS);
   return pred_context;
 }
 
 // Returns a context number for the given MB prediction signal
+//
 // Signal the uni-directional compound reference frame pair as
-// either (BWDREF, ALTREF), or (LAST, LAST2)/(LAST, GOLDEN),
-// conditioning on the pair is known as uni-directional.
-#define CHECK_LAST2_OR_GOLDEN(ref_frame) \
-  ((ref_frame) == LAST2_FRAME || (ref_frame) == GOLDEN_FRAME)
-int av1_get_pred_context_uni_comp_ref_p1(const AV1_COMMON *cm,
-                                         const MACROBLOCKD *xd) {
+// either (LAST, LAST2), or (LAST, LAST3) / (LAST, GOLDEN),
+// conditioning on the pair is known as one of the above three.
+//
+// 3 contexts: Voting is used to compare the count of LAST2_FRAME with the
+//             total count of LAST3/GOLDEN from the spatial neighbors.
+int av1_get_pred_context_uni_comp_ref_p1(const MACROBLOCKD *xd) {
   int pred_context;
   const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
   const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
   const int above_in_image = xd->up_available;
   const int left_in_image = xd->left_available;
 
-  (void)cm;
+  // Count of LAST2
+  int last2_count = 0;
+  // Count of LAST3 or GOLDEN
+  int last3_or_gld_count = 0;
 
-  if (above_in_image && left_in_image) {  // both edges available
-    const int above_intra = !is_inter_block(above_mbmi);
-    const int left_intra = !is_inter_block(left_mbmi);
-
-    if (above_intra && left_intra) {  // intra/intra
-      pred_context = 2;
-    } else if (above_intra || left_intra) {  // intra/inter
-      const MB_MODE_INFO *inter_mbmi = above_intra ? left_mbmi : above_mbmi;
-
-      if (!has_second_ref(inter_mbmi)) {  // single pred
-        if (CHECK_LAST2_OR_GOLDEN(inter_mbmi->ref_frame[0]))
-          pred_context = 1 + 2 * (inter_mbmi->ref_frame[0] == LAST2_FRAME);
-        else
-          pred_context = 2;
-      } else {  // comp pred
-        if (CHECK_LAST2_OR_GOLDEN(inter_mbmi->ref_frame[1]))
-          pred_context = 4 * (inter_mbmi->ref_frame[1] == LAST2_FRAME);
-        else
-          pred_context = 2;
-      }
-    } else {  // inter/inter
-      const int a_sg = !has_second_ref(above_mbmi);
-      const int l_sg = !has_second_ref(left_mbmi);
-      const MV_REFERENCE_FRAME frfa = above_mbmi->ref_frame[0];
-      const MV_REFERENCE_FRAME frfl = left_mbmi->ref_frame[0];
-      const MV_REFERENCE_FRAME brfa = above_mbmi->ref_frame[1];
-      const MV_REFERENCE_FRAME brfl = left_mbmi->ref_frame[1];
-
-      if (a_sg && l_sg) {  // single/single
-        if (CHECK_LAST2_OR_GOLDEN(frfa) && (frfa == frfl || frfl == LAST_FRAME))
-          pred_context = 1 + 2 * (frfa == LAST2_FRAME);
-        else if (frfa == LAST_FRAME && CHECK_LAST2_OR_GOLDEN(frfl))
-          pred_context = 1 + 2 * (frfl == LAST2_FRAME);
-        else
-          pred_context = 2;
-      } else if (l_sg || a_sg) {  // single/comp
-        const MV_REFERENCE_FRAME brfc = a_sg ? brfl : brfa;
-
-        if (CHECK_LAST2_OR_GOLDEN(brfc))
-          pred_context = 4 * (brfc == LAST2_FRAME);
-        if (CHECK_LAST2_OR_GOLDEN(frfa) && (frfa == frfl || frfl == LAST_FRAME))
-          pred_context = 1 + 2 * (frfa == LAST2_FRAME);
-        else if (frfa == LAST_FRAME && CHECK_LAST2_OR_GOLDEN(frfl))
-          pred_context = 1 + 2 * (frfl == LAST2_FRAME);
-        else
-          pred_context = 2;
-      } else {  // comp/comp
-        if (CHECK_LAST2_OR_GOLDEN(brfa) &&
-            (brfa == brfl || !CHECK_LAST2_OR_GOLDEN(brfl)))
-          pred_context = 4 * (brfa == LAST2_FRAME);
-        else if (!CHECK_LAST2_OR_GOLDEN(brfa) && CHECK_LAST2_OR_GOLDEN(brfl))
-          pred_context = 4 * (brfl == LAST2_FRAME);
-        else if (CHECK_LAST2_OR_GOLDEN(frfa) &&
-                 (frfa == frfl || frfl == LAST_FRAME))
-          pred_context = 1 + 2 * (frfa == LAST2_FRAME);
-        else if (frfa == LAST_FRAME && CHECK_LAST2_OR_GOLDEN(frfl))
-          pred_context = 1 + 2 * (frfl == LAST2_FRAME);
-        else
-          pred_context = 2;
-      }
+  if (above_in_image && is_inter_block(above_mbmi)) {
+    last2_count = (above_mbmi->ref_frame[0] == LAST2_FRAME) ? last2_count + 1
+                                                            : last2_count;
+    last3_or_gld_count = CHECK_GOLDEN_OR_LAST3(above_mbmi->ref_frame[0])
+                             ? last3_or_gld_count + 1
+                             : last3_or_gld_count;
+    if (has_second_ref(above_mbmi)) {
+      last2_count = (above_mbmi->ref_frame[1] == LAST2_FRAME) ? last2_count + 1
+                                                              : last2_count;
+      last3_or_gld_count = CHECK_GOLDEN_OR_LAST3(above_mbmi->ref_frame[1])
+                               ? last3_or_gld_count + 1
+                               : last3_or_gld_count;
     }
-  } else if (above_in_image || left_in_image) {  // one edge available
-    const MB_MODE_INFO *edge_mbmi = above_in_image ? above_mbmi : left_mbmi;
-
-    if (!is_inter_block(edge_mbmi)) {  // intra
-      pred_context = 2;
-    } else {                             // inter
-      if (!has_second_ref(edge_mbmi)) {  // single pred
-        if (CHECK_LAST2_OR_GOLDEN(edge_mbmi->ref_frame[0]))
-          pred_context = 1 + 2 * (edge_mbmi->ref_frame[0] == LAST2_FRAME);
-        else
-          pred_context = 2;
-      } else {  // comp pred
-        if (CHECK_LAST2_OR_GOLDEN(edge_mbmi->ref_frame[1]))
-          pred_context = 4 * (edge_mbmi->ref_frame[1] == LAST2_FRAME);
-        else
-          pred_context = 2;
-      }
-    }
-  } else {  // no edges available
-    pred_context = 2;
   }
 
+  if (left_in_image && is_inter_block(left_mbmi)) {
+    last2_count = (left_mbmi->ref_frame[0] == LAST2_FRAME) ? last2_count + 1
+                                                           : last2_count;
+    last3_or_gld_count = CHECK_GOLDEN_OR_LAST3(left_mbmi->ref_frame[0])
+                             ? last3_or_gld_count + 1
+                             : last3_or_gld_count;
+    if (has_second_ref(left_mbmi)) {
+      last2_count = (left_mbmi->ref_frame[1] == LAST2_FRAME) ? last2_count + 1
+                                                             : last2_count;
+      last3_or_gld_count = CHECK_GOLDEN_OR_LAST3(left_mbmi->ref_frame[1])
+                               ? last3_or_gld_count + 1
+                               : last3_or_gld_count;
+    }
+  }
+
+  pred_context = (last2_count == last3_or_gld_count)
+                     ? 1
+                     : ((last2_count < last3_or_gld_count) ? 0 : 2);
+
+  assert(pred_context >= 0 && pred_context < UNI_COMP_REF_CONTEXTS);
+  return pred_context;
+}
+
+// Returns a context number for the given MB prediction signal
+//
+// Signal the uni-directional compound reference frame pair as
+// either (LAST, LAST3) or (LAST, GOLDEN),
+// conditioning on the pair is known as one of the above two.
+//
+// 3 contexts: Voting is used to compare the count of LAST3_FRAME with the
+//             total count of GOLDEN_FRAME from the spatial neighbors.
+int av1_get_pred_context_uni_comp_ref_p2(const MACROBLOCKD *xd) {
+  int pred_context;
+  const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
+  const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
+  const int above_in_image = xd->up_available;
+  const int left_in_image = xd->left_available;
+
+  // Count of LAST3
+  int last3_count = 0;
+  // Count of GOLDEN
+  int gld_count = 0;
+
+  if (above_in_image && is_inter_block(above_mbmi)) {
+    last3_count = (above_mbmi->ref_frame[0] == LAST3_FRAME) ? last3_count + 1
+                                                            : last3_count;
+    gld_count =
+        (above_mbmi->ref_frame[0] == GOLDEN_FRAME) ? gld_count + 1 : gld_count;
+    if (has_second_ref(above_mbmi)) {
+      last3_count = (above_mbmi->ref_frame[1] == LAST3_FRAME) ? last3_count + 1
+                                                              : last3_count;
+      gld_count = (above_mbmi->ref_frame[1] == GOLDEN_FRAME) ? gld_count + 1
+                                                             : gld_count;
+    }
+  }
+
+  if (left_in_image && is_inter_block(left_mbmi)) {
+    last3_count = (left_mbmi->ref_frame[0] == LAST3_FRAME) ? last3_count + 1
+                                                           : last3_count;
+    gld_count =
+        (left_mbmi->ref_frame[0] == GOLDEN_FRAME) ? gld_count + 1 : gld_count;
+    if (has_second_ref(left_mbmi)) {
+      last3_count = (left_mbmi->ref_frame[1] == LAST3_FRAME) ? last3_count + 1
+                                                             : last3_count;
+      gld_count =
+          (left_mbmi->ref_frame[1] == GOLDEN_FRAME) ? gld_count + 1 : gld_count;
+    }
+  }
+
+  pred_context =
+      (last3_count == gld_count) ? 1 : ((last3_count < gld_count) ? 0 : 2);
+
   assert(pred_context >= 0 && pred_context < UNI_COMP_REF_CONTEXTS);
   return pred_context;
 }
@@ -592,9 +562,6 @@
 #define CHECK_LAST_OR_LAST2(ref_frame) \
   ((ref_frame == LAST_FRAME) || (ref_frame == LAST2_FRAME))
 
-#define CHECK_GOLDEN_OR_LAST3(ref_frame) \
-  ((ref_frame == GOLDEN_FRAME) || (ref_frame == LAST3_FRAME))
-
 // Returns a context number for the given MB prediction signal
 // Signal the first reference frame for a compound mode be either
 // GOLDEN/LAST3, or LAST/LAST2.
diff --git a/av1/common/pred_common.h b/av1/common/pred_common.h
index a4f2482..610a2c3 100644
--- a/av1/common/pred_common.h
+++ b/av1/common/pred_common.h
@@ -109,32 +109,62 @@
 #endif
 
 #if CONFIG_EXT_COMP_REFS
-int av1_get_comp_reference_type_context(const AV1_COMMON *cm,
-                                        const MACROBLOCKD *xd);
+int av1_get_comp_reference_type_context(const MACROBLOCKD *xd);
 
 static INLINE aom_prob av1_get_comp_reference_type_prob(const AV1_COMMON *cm,
                                                         const MACROBLOCKD *xd) {
-  return cm->fc
-      ->comp_ref_type_prob[av1_get_comp_reference_type_context(cm, xd)];
+  return cm->fc->comp_ref_type_prob[av1_get_comp_reference_type_context(xd)];
 }
 
-int av1_get_pred_context_uni_comp_ref_p(const AV1_COMMON *cm,
-                                        const MACROBLOCKD *xd);
+int av1_get_pred_context_uni_comp_ref_p(const MACROBLOCKD *xd);
 
 static INLINE aom_prob av1_get_pred_prob_uni_comp_ref_p(const AV1_COMMON *cm,
                                                         const MACROBLOCKD *xd) {
-  const int pred_context = av1_get_pred_context_uni_comp_ref_p(cm, xd);
+  const int pred_context = av1_get_pred_context_uni_comp_ref_p(xd);
   return cm->fc->uni_comp_ref_prob[pred_context][0];
 }
 
-int av1_get_pred_context_uni_comp_ref_p1(const AV1_COMMON *cm,
-                                         const MACROBLOCKD *xd);
+int av1_get_pred_context_uni_comp_ref_p1(const MACROBLOCKD *xd);
 
 static INLINE aom_prob
 av1_get_pred_prob_uni_comp_ref_p1(const AV1_COMMON *cm, const MACROBLOCKD *xd) {
-  const int pred_context = av1_get_pred_context_uni_comp_ref_p1(cm, xd);
+  const int pred_context = av1_get_pred_context_uni_comp_ref_p1(xd);
   return cm->fc->uni_comp_ref_prob[pred_context][1];
 }
+
+int av1_get_pred_context_uni_comp_ref_p2(const MACROBLOCKD *xd);
+
+static INLINE aom_prob
+av1_get_pred_prob_uni_comp_ref_p2(const AV1_COMMON *cm, const MACROBLOCKD *xd) {
+  const int pred_context = av1_get_pred_context_uni_comp_ref_p2(xd);
+  return cm->fc->uni_comp_ref_prob[pred_context][2];
+}
+
+#if CONFIG_NEW_MULTISYMBOL
+static INLINE aom_cdf_prob *av1_get_comp_reference_type_cdf(
+    const MACROBLOCKD *xd) {
+  const int pred_context = av1_get_comp_reference_type_context(xd);
+  return xd->tile_ctx->comp_ref_type_cdf[pred_context];
+}
+
+static INLINE aom_cdf_prob *av1_get_pred_cdf_uni_comp_ref_p(
+    const MACROBLOCKD *xd) {
+  const int pred_context = av1_get_pred_context_uni_comp_ref_p(xd);
+  return xd->tile_ctx->uni_comp_ref_cdf[pred_context][0];
+}
+
+static INLINE aom_cdf_prob *av1_get_pred_cdf_uni_comp_ref_p1(
+    const MACROBLOCKD *xd) {
+  const int pred_context = av1_get_pred_context_uni_comp_ref_p1(xd);
+  return xd->tile_ctx->uni_comp_ref_cdf[pred_context][1];
+}
+
+static INLINE aom_cdf_prob *av1_get_pred_cdf_uni_comp_ref_p2(
+    const MACROBLOCKD *xd) {
+  const int pred_context = av1_get_pred_context_uni_comp_ref_p2(xd);
+  return xd->tile_ctx->uni_comp_ref_cdf[pred_context][2];
+}
+#endif  // CONFIG_NEW_MULTISYMBOL
 #endif  // CONFIG_EXT_COMP_REFS
 
 int av1_get_pred_context_comp_ref_p(const AV1_COMMON *cm,
diff --git a/av1/decoder/decodemv.c b/av1/decoder/decodemv.c
index d4153af..2f47e79 100644
--- a/av1/decoder/decodemv.c
+++ b/av1/decoder/decodemv.c
@@ -1354,10 +1354,21 @@
 static REFERENCE_MODE read_comp_reference_type(AV1_COMMON *cm,
                                                const MACROBLOCKD *xd,
                                                aom_reader *r) {
-  const int ctx = av1_get_comp_reference_type_context(cm, xd);
+  const int ctx = av1_get_comp_reference_type_context(xd);
 #if USE_UNI_COMP_REFS
-  const COMP_REFERENCE_TYPE comp_ref_type = (COMP_REFERENCE_TYPE)aom_read(
-      r, cm->fc->comp_ref_type_prob[ctx], ACCT_STR);
+  COMP_REFERENCE_TYPE comp_ref_type;
+#if CONFIG_VAR_REFS
+  if ((L_OR_L2(cm) || L3_OR_G(cm)) && BWD_OR_ALT(cm))
+    if (L_AND_L2(cm) || L_AND_L3(cm) || L_AND_G(cm) || BWD_AND_ALT(cm))
+#endif  // CONFIG_VAR_REFS
+      comp_ref_type = (COMP_REFERENCE_TYPE)aom_read(
+          r, cm->fc->comp_ref_type_prob[ctx], ACCT_STR);
+#if CONFIG_VAR_REFS
+    else
+      comp_ref_type = BIDIR_COMP_REFERENCE;
+  else
+    comp_ref_type = UNIDIR_COMP_REFERENCE;
+#endif  // CONFIG_VAR_REFS
 #else   // !USE_UNI_COMP_REFS
   // TODO(zoeliu): Temporarily turn off uni-directional comp refs
   const COMP_REFERENCE_TYPE comp_ref_type = BIDIR_COMP_REFERENCE;
@@ -1395,22 +1406,54 @@
 #endif  // !USE_UNI_COMP_REFS
 
       if (comp_ref_type == UNIDIR_COMP_REFERENCE) {
-        const int ctx = av1_get_pred_context_uni_comp_ref_p(cm, xd);
-        const int bit = aom_read(r, fc->uni_comp_ref_prob[ctx][0], ACCT_STR);
+        const int ctx = av1_get_pred_context_uni_comp_ref_p(xd);
+        int bit;
+#if CONFIG_VAR_REFS
+        if ((L_AND_L2(cm) || L_AND_L3(cm) || L_AND_G(cm)) && BWD_AND_ALT(cm))
+#endif  // CONFIG_VAR_REFS
+          bit = aom_read(r, fc->uni_comp_ref_prob[ctx][0], ACCT_STR);
+#if CONFIG_VAR_REFS
+        else
+          bit = BWD_AND_ALT(cm);
+#endif  // CONFIG_VAR_REFS
         if (counts) ++counts->uni_comp_ref[ctx][0][bit];
 
         if (bit) {
           ref_frame[0] = BWDREF_FRAME;
           ref_frame[1] = ALTREF_FRAME;
         } else {
-          const int ctx1 = av1_get_pred_context_uni_comp_ref_p1(cm, xd);
-          const int bit1 =
-              aom_read(r, fc->uni_comp_ref_prob[ctx1][1], ACCT_STR);
+          const int ctx1 = av1_get_pred_context_uni_comp_ref_p1(xd);
+          int bit1;
+#if CONFIG_VAR_REFS
+          if (L_AND_L2(cm) && (L_AND_L3(cm) || L_AND_G(cm)))
+#endif  // CONFIG_VAR_REFS
+            bit1 = aom_read(r, fc->uni_comp_ref_prob[ctx1][1], ACCT_STR);
+#if CONFIG_VAR_REFS
+          else
+            bit1 = L_AND_L3(cm) || L_AND_G(cm);
+#endif  // CONFIG_VAR_REFS
           if (counts) ++counts->uni_comp_ref[ctx1][1][bit1];
 
           if (bit1) {
-            ref_frame[0] = LAST_FRAME;
-            ref_frame[1] = GOLDEN_FRAME;
+            const int ctx2 = av1_get_pred_context_uni_comp_ref_p2(xd);
+            int bit2;
+#if CONFIG_VAR_REFS
+            if (L_AND_L3(cm) && L_AND_G(cm))
+#endif  // CONFIG_VAR_REFS
+              bit2 = aom_read(r, fc->uni_comp_ref_prob[ctx2][2], ACCT_STR);
+#if CONFIG_VAR_REFS
+            else
+              bit2 = L_AND_G(cm);
+#endif  // CONFIG_VAR_REFS
+            if (counts) ++counts->uni_comp_ref[ctx2][2][bit2];
+
+            if (bit2) {
+              ref_frame[0] = LAST_FRAME;
+              ref_frame[1] = GOLDEN_FRAME;
+            } else {
+              ref_frame[0] = LAST_FRAME;
+              ref_frame[1] = LAST3_FRAME;
+            }
           } else {
             ref_frame[0] = LAST_FRAME;
             ref_frame[1] = LAST2_FRAME;
@@ -1419,6 +1462,8 @@
 
         return;
       }
+
+      assert(comp_ref_type == BIDIR_COMP_REFERENCE);
 #endif  // CONFIG_EXT_COMP_REFS
 
 // Normative in decoder (for low delay)
@@ -2077,9 +2122,7 @@
 
   int8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
 #define FRAME_TO_CHECK 1
-  if (cm->current_video_frame == FRAME_TO_CHECK
-      // && cm->show_frame == 0
-      ) {
+  if (cm->current_video_frame == FRAME_TO_CHECK /*&& cm->show_frame == 0*/) {
     printf(
         "=== DECODER ===: "
         "Frame=%d, (mi_row,mi_col)=(%d,%d), mode=%d, bsize=%d, "
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 7ecd203..dcf3d29 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -1098,9 +1098,18 @@
       const COMP_REFERENCE_TYPE comp_ref_type = has_uni_comp_refs(mbmi)
                                                     ? UNIDIR_COMP_REFERENCE
                                                     : BIDIR_COMP_REFERENCE;
-
 #if USE_UNI_COMP_REFS
-      aom_write(w, comp_ref_type, av1_get_comp_reference_type_prob(cm, xd));
+#if CONFIG_VAR_REFS
+      if ((L_OR_L2(cm) || L3_OR_G(cm)) && BWD_OR_ALT(cm))
+        if (L_AND_L2(cm) || L_AND_L3(cm) || L_AND_G(cm) || BWD_AND_ALT(cm))
+#endif  // CONFIG_VAR_REFS
+          aom_write(w, comp_ref_type, av1_get_comp_reference_type_prob(cm, xd));
+#if CONFIG_VAR_REFS
+        else
+          assert(comp_ref_type == BIDIR_COMP_REFERENCE);
+      else
+        assert(comp_ref_type == UNIDIR_COMP_REFERENCE);
+#endif  // CONFIG_VAR_REFS
 #else   // !USE_UNI_COMP_REFS
       // NOTE: uni-directional comp refs disabled
       assert(comp_ref_type == BIDIR_COMP_REFERENCE);
@@ -1108,14 +1117,41 @@
 
       if (comp_ref_type == UNIDIR_COMP_REFERENCE) {
         const int bit = mbmi->ref_frame[0] == BWDREF_FRAME;
-        aom_write(w, bit, av1_get_pred_prob_uni_comp_ref_p(cm, xd));
+#if CONFIG_VAR_REFS
+        if ((L_AND_L2(cm) || L_AND_L3(cm) || L_AND_G(cm)) && BWD_AND_ALT(cm))
+#endif  // CONFIG_VAR_REFS
+          aom_write(w, bit, av1_get_pred_prob_uni_comp_ref_p(cm, xd));
+
         if (!bit) {
-          const int bit1 = mbmi->ref_frame[1] == GOLDEN_FRAME;
-          aom_write(w, bit1, av1_get_pred_prob_uni_comp_ref_p1(cm, xd));
+          assert(mbmi->ref_frame[0] == LAST_FRAME);
+#if CONFIG_VAR_REFS
+          if (L_AND_L2(cm) && (L_AND_L3(cm) || L_AND_G(cm))) {
+#endif  // CONFIG_VAR_REFS
+            const int bit1 = mbmi->ref_frame[1] == LAST3_FRAME ||
+                             mbmi->ref_frame[1] == GOLDEN_FRAME;
+            aom_write(w, bit1, av1_get_pred_prob_uni_comp_ref_p1(cm, xd));
+
+            if (bit1) {
+#if CONFIG_VAR_REFS
+              if (L_AND_L3(cm) && L_AND_G(cm)) {
+#endif  // CONFIG_VAR_REFS
+                const int bit2 = mbmi->ref_frame[1] == GOLDEN_FRAME;
+                aom_write(w, bit2, av1_get_pred_prob_uni_comp_ref_p2(cm, xd));
+#if CONFIG_VAR_REFS
+              }
+#endif  // CONFIG_VAR_REFS
+            }
+#if CONFIG_VAR_REFS
+          }
+#endif  // CONFIG_VAR_REFS
+        } else {
+          assert(mbmi->ref_frame[1] == ALTREF_FRAME);
         }
 
         return;
       }
+
+      assert(comp_ref_type == BIDIR_COMP_REFERENCE);
 #endif  // CONFIG_EXT_COMP_REFS
 
 #if CONFIG_EXT_REFS
@@ -2311,7 +2347,7 @@
   m = xd->mi[0];
   if (is_inter_block(&m->mbmi)) {
 #define FRAME_TO_CHECK 1
-    if (cm->current_video_frame == FRAME_TO_CHECK && cm->show_frame == 0) {
+    if (cm->current_video_frame == FRAME_TO_CHECK /* && cm->show_frame == 1*/) {
       const MB_MODE_INFO *const mbmi = &m->mbmi;
       const BLOCK_SIZE bsize = mbmi->sb_type;
 
@@ -4608,7 +4644,7 @@
         }
       }
     }
-#endif
+
     if (cm->reference_mode != SINGLE_REFERENCE) {
 #if CONFIG_EXT_COMP_REFS
       for (i = 0; i < COMP_REF_TYPE_CONTEXTS; i++)
@@ -4621,7 +4657,6 @@
                                     counts->uni_comp_ref[i][j], probwt);
 #endif  // CONFIG_EXT_COMP_REFS
 
-#if !CONFIG_NEW_MULTISYMBOL
       for (i = 0; i < REF_CONTEXTS; i++) {
 #if CONFIG_EXT_REFS
         for (j = 0; j < (FWD_REFS - 1); j++) {
@@ -4639,8 +4674,8 @@
         }
 #endif  // CONFIG_EXT_REFS
       }
-#endif  // CONFIG_NEW_MULTISYMBOL
     }
+#endif  // CONFIG_NEW_MULTISYMBOL
 
 #if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
     for (i = 0; i < COMP_INTER_MODE_CONTEXTS; i++)
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index 32d244c..7d3d44e 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -1613,17 +1613,21 @@
           // TODO(zoeliu): Temporarily turn off uni-directional comp refs
           assert(comp_ref_type == BIDIR_COMP_REFERENCE);
 #endif  // !USE_UNI_COMP_REFS
-          counts->comp_ref_type[av1_get_comp_reference_type_context(cm, xd)]
+          counts->comp_ref_type[av1_get_comp_reference_type_context(xd)]
                                [comp_ref_type]++;
 
           if (comp_ref_type == UNIDIR_COMP_REFERENCE) {
             const int bit = (ref0 == BWDREF_FRAME);
-            counts->uni_comp_ref[av1_get_pred_context_uni_comp_ref_p(cm, xd)][0]
+            counts->uni_comp_ref[av1_get_pred_context_uni_comp_ref_p(xd)][0]
                                 [bit]++;
             if (!bit) {
-              const int bit1 = (ref1 == GOLDEN_FRAME);
-              counts->uni_comp_ref[av1_get_pred_context_uni_comp_ref_p1(cm, xd)]
-                                  [1][bit1]++;
+              const int bit1 = (ref1 == LAST3_FRAME || ref1 == GOLDEN_FRAME);
+              counts->uni_comp_ref[av1_get_pred_context_uni_comp_ref_p1(xd)][1]
+                                  [bit1]++;
+              if (bit1) {
+                counts->uni_comp_ref[av1_get_pred_context_uni_comp_ref_p2(xd)]
+                                    [2][ref1 == GOLDEN_FRAME]++;
+              }
             }
           } else {
 #endif  // CONFIG_EXT_COMP_REFS
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 91ee497..54f4102 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -4184,7 +4184,7 @@
       map[cpi->lst_fb_idxes[2]] == map[cpi->lst_fb_idxes[1]];
   const int gld_is_last2 = map[cpi->gld_fb_idx] == map[cpi->lst_fb_idxes[1]];
   const int gld_is_last3 = map[cpi->gld_fb_idx] == map[cpi->lst_fb_idxes[2]];
-#else
+#else  // !CONFIG_ONE_SIDED_COMPOUND
   const int bwd_is_last = map[cpi->bwd_fb_idx] == map[cpi->lst_fb_idxes[0]];
   const int alt_is_last = map[cpi->alt_fb_idx] == map[cpi->lst_fb_idxes[0]];
 
@@ -4198,12 +4198,12 @@
 
   const int bwd_is_gld = map[cpi->bwd_fb_idx] == map[cpi->gld_fb_idx];
 
-#endif
+#endif  // CONFIG_ONE_SIDED_COMPOUND
   const int last2_is_alt = map[cpi->lst_fb_idxes[1]] == map[cpi->alt_fb_idx];
   const int last3_is_alt = map[cpi->lst_fb_idxes[2]] == map[cpi->alt_fb_idx];
   const int gld_is_alt = map[cpi->gld_fb_idx] == map[cpi->alt_fb_idx];
   const int bwd_is_alt = map[cpi->bwd_fb_idx] == map[cpi->alt_fb_idx];
-#else
+#else   // !CONFIG_EXT_REFS
   const int gld_is_last = map[cpi->gld_fb_idx] == map[cpi->lst_fb_idx];
   const int gld_is_alt = map[cpi->gld_fb_idx] == map[cpi->alt_fb_idx];
   const int alt_is_last = map[cpi->alt_fb_idx] == map[cpi->lst_fb_idx];
@@ -4229,12 +4229,7 @@
 
   if (last3_is_last || last3_is_last2 || last3_is_alt) flags &= ~AOM_LAST3_FLAG;
 
-#if CONFIG_EXT_COMP_REFS
-  if (gld_is_last2) flags &= ~AOM_GOLD_FLAG;
-  if (gld_is_last3) flags &= ~AOM_LAST3_FLAG;
-#else
   if (gld_is_last2 || gld_is_last3) flags &= ~AOM_GOLD_FLAG;
-#endif  // CONFIG_EXT_COMP_REFS
 
 #if CONFIG_ONE_SIDED_COMPOUND  // Changes LL & HL bitstream
   /* Allow biprediction between two identical frames (e.g. bwd_is_last = 1) */
@@ -4380,11 +4375,14 @@
   }
   printf(
       "\nFrame=%5d, encode_update_type[%5d]=%1d, show_existing_frame=%d, "
-      "y_stride=%4d, uv_stride=%4d, width=%4d, height=%4d\n",
+      "source_alt_ref_active=%d, refresh_alt_ref_frame=%d, rf_level=%d, "
+      "y_stride=%4d, uv_stride=%4d, cm->width=%4d, cm->height=%4d\n",
       cm->current_video_frame, cpi->twopass.gf_group.index,
       cpi->twopass.gf_group.update_type[cpi->twopass.gf_group.index],
-      cm->show_existing_frame, recon_buf->y_stride, recon_buf->uv_stride,
-      cm->width, cm->height);
+      cm->show_existing_frame, cpi->rc.source_alt_ref_active,
+      cpi->refresh_alt_ref_frame,
+      cpi->twopass.gf_group.rf_level[cpi->twopass.gf_group.index],
+      recon_buf->y_stride, recon_buf->uv_stride, cm->width, cm->height);
 
   // --- Y ---
   for (h = 0; h < cm->height; ++h) {
diff --git a/av1/encoder/rd.c b/av1/encoder/rd.c
index 2fafa4d..1c9ed43 100644
--- a/av1/encoder/rd.c
+++ b/av1/encoder/rd.c
@@ -1061,6 +1061,7 @@
 
 #if CONFIG_EXT_COMP_REFS
   rd->thresh_mult[THR_COMP_NEAREST_NEARESTLL2] += 1000;
+  rd->thresh_mult[THR_COMP_NEAREST_NEARESTLL3] += 1000;
   rd->thresh_mult[THR_COMP_NEAREST_NEARESTLG] += 1000;
   rd->thresh_mult[THR_COMP_NEAREST_NEARESTBA] += 1000;
 #endif  // CONFIG_EXT_COMP_REFS
@@ -1081,6 +1082,7 @@
   rd->thresh_mult[THR_COMP_NEARESTGB] += 1000;
 #if CONFIG_EXT_COMP_REFS
   rd->thresh_mult[THR_COMP_NEARESTLL2] += 1000;
+  rd->thresh_mult[THR_COMP_NEARESTLL3] += 1000;
   rd->thresh_mult[THR_COMP_NEARESTLG] += 1000;
   rd->thresh_mult[THR_COMP_NEARESTBA] += 1000;
 #endif  // CONFIG_EXT_COMP_REFS
@@ -1158,8 +1160,6 @@
   rd->thresh_mult[THR_COMP_ZERO_ZEROGB] += 2500;
 
 #if CONFIG_EXT_COMP_REFS
-  rd->thresh_mult[THR_COMP_NEAREST_NEARLL2] += 1200;
-  rd->thresh_mult[THR_COMP_NEAR_NEARESTLL2] += 1200;
   rd->thresh_mult[THR_COMP_NEAR_NEARLL2] += 1200;
   rd->thresh_mult[THR_COMP_NEAREST_NEWLL2] += 1500;
   rd->thresh_mult[THR_COMP_NEW_NEARESTLL2] += 1500;
@@ -1168,8 +1168,14 @@
   rd->thresh_mult[THR_COMP_NEW_NEWLL2] += 2000;
   rd->thresh_mult[THR_COMP_ZERO_ZEROLL2] += 2500;
 
-  rd->thresh_mult[THR_COMP_NEAREST_NEARLG] += 1200;
-  rd->thresh_mult[THR_COMP_NEAR_NEARESTLG] += 1200;
+  rd->thresh_mult[THR_COMP_NEAR_NEARLL3] += 1200;
+  rd->thresh_mult[THR_COMP_NEAREST_NEWLL3] += 1500;
+  rd->thresh_mult[THR_COMP_NEW_NEARESTLL3] += 1500;
+  rd->thresh_mult[THR_COMP_NEAR_NEWLL3] += 1700;
+  rd->thresh_mult[THR_COMP_NEW_NEARLL3] += 1700;
+  rd->thresh_mult[THR_COMP_NEW_NEWLL3] += 2000;
+  rd->thresh_mult[THR_COMP_ZERO_ZEROLL3] += 2500;
+
   rd->thresh_mult[THR_COMP_NEAR_NEARLG] += 1200;
   rd->thresh_mult[THR_COMP_NEAREST_NEWLG] += 1500;
   rd->thresh_mult[THR_COMP_NEW_NEARESTLG] += 1500;
@@ -1178,8 +1184,6 @@
   rd->thresh_mult[THR_COMP_NEW_NEWLG] += 2000;
   rd->thresh_mult[THR_COMP_ZERO_ZEROLG] += 2500;
 
-  rd->thresh_mult[THR_COMP_NEAREST_NEARBA] += 1200;
-  rd->thresh_mult[THR_COMP_NEAR_NEARESTBA] += 1200;
   rd->thresh_mult[THR_COMP_NEAR_NEARBA] += 1200;
   rd->thresh_mult[THR_COMP_NEAREST_NEWBA] += 1500;
   rd->thresh_mult[THR_COMP_NEW_NEARESTBA] += 1500;
@@ -1216,6 +1220,8 @@
 #if CONFIG_EXT_COMP_REFS
   rd->thresh_mult[THR_COMP_NEARLL2] += 1500;
   rd->thresh_mult[THR_COMP_NEWLL2] += 2000;
+  rd->thresh_mult[THR_COMP_NEARLL3] += 1500;
+  rd->thresh_mult[THR_COMP_NEWLL3] += 2000;
   rd->thresh_mult[THR_COMP_NEARLG] += 1500;
   rd->thresh_mult[THR_COMP_NEWLG] += 2000;
   rd->thresh_mult[THR_COMP_NEARBA] += 1500;
@@ -1238,6 +1244,7 @@
 
 #if CONFIG_EXT_COMP_REFS
   rd->thresh_mult[THR_COMP_ZEROLL2] += 2500;
+  rd->thresh_mult[THR_COMP_ZEROLL3] += 2500;
   rd->thresh_mult[THR_COMP_ZEROLG] += 2500;
   rd->thresh_mult[THR_COMP_ZEROBA] += 2500;
 #endif  // CONFIG_EXT_COMP_REFS
diff --git a/av1/encoder/rd.h b/av1/encoder/rd.h
index c9de1cd..efa6450 100644
--- a/av1/encoder/rd.h
+++ b/av1/encoder/rd.h
@@ -158,6 +158,7 @@
   THR_COMP_NEAREST_NEARESTGB,
 #if CONFIG_EXT_COMP_REFS
   THR_COMP_NEAREST_NEARESTLL2,
+  THR_COMP_NEAREST_NEARESTLL3,
   THR_COMP_NEAREST_NEARESTLG,
   THR_COMP_NEAREST_NEARESTBA,
 #endif  // CONFIG_EXT_COMP_REFS
@@ -178,6 +179,7 @@
   THR_COMP_NEARESTGB,
 #if CONFIG_EXT_COMP_REFS
   THR_COMP_NEARESTLL2,
+  THR_COMP_NEARESTLL3,
   THR_COMP_NEARESTLG,
   THR_COMP_NEARESTBA,
 #endif  // CONFIG_EXT_COMP_REFS
@@ -265,8 +267,6 @@
   THR_COMP_ZERO_ZEROGB,
 
 #if CONFIG_EXT_COMP_REFS
-  THR_COMP_NEAR_NEARESTLL2,
-  THR_COMP_NEAREST_NEARLL2,
   THR_COMP_NEAR_NEARLL2,
   THR_COMP_NEW_NEARESTLL2,
   THR_COMP_NEAREST_NEWLL2,
@@ -275,8 +275,14 @@
   THR_COMP_NEW_NEWLL2,
   THR_COMP_ZERO_ZEROLL2,
 
-  THR_COMP_NEAR_NEARESTLG,
-  THR_COMP_NEAREST_NEARLG,
+  THR_COMP_NEAR_NEARLL3,
+  THR_COMP_NEW_NEARESTLL3,
+  THR_COMP_NEAREST_NEWLL3,
+  THR_COMP_NEW_NEARLL3,
+  THR_COMP_NEAR_NEWLL3,
+  THR_COMP_NEW_NEWLL3,
+  THR_COMP_ZERO_ZEROLL3,
+
   THR_COMP_NEAR_NEARLG,
   THR_COMP_NEW_NEARESTLG,
   THR_COMP_NEAREST_NEWLG,
@@ -285,8 +291,6 @@
   THR_COMP_NEW_NEWLG,
   THR_COMP_ZERO_ZEROLG,
 
-  THR_COMP_NEAR_NEARESTBA,
-  THR_COMP_NEAREST_NEARBA,
   THR_COMP_NEAR_NEARBA,
   THR_COMP_NEW_NEARESTBA,
   THR_COMP_NEAREST_NEWBA,
@@ -323,6 +327,8 @@
 #if CONFIG_EXT_COMP_REFS
   THR_COMP_NEARLL2,
   THR_COMP_NEWLL2,
+  THR_COMP_NEARLL3,
+  THR_COMP_NEWLL3,
   THR_COMP_NEARLG,
   THR_COMP_NEWLG,
   THR_COMP_NEARBA,
@@ -345,6 +351,7 @@
 
 #if CONFIG_EXT_COMP_REFS
   THR_COMP_ZEROLL2,
+  THR_COMP_ZEROLL3,
   THR_COMP_ZEROLG,
   THR_COMP_ZEROBA,
 #endif  // CONFIG_EXT_COMP_REFS
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index 90fc215..b3e517e 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -266,6 +266,7 @@
 
 #if CONFIG_EXT_COMP_REFS
   { NEAREST_NEARESTMV, { LAST_FRAME, LAST2_FRAME } },
+  { NEAREST_NEARESTMV, { LAST_FRAME, LAST3_FRAME } },
   { NEAREST_NEARESTMV, { LAST_FRAME, GOLDEN_FRAME } },
   { NEAREST_NEARESTMV, { BWDREF_FRAME, ALTREF_FRAME } },
 #endif  // CONFIG_EXT_COMP_REFS
@@ -287,6 +288,7 @@
 
 #if CONFIG_EXT_COMP_REFS
   { NEARESTMV, { LAST_FRAME, LAST2_FRAME } },
+  { NEARESTMV, { LAST_FRAME, LAST3_FRAME } },
   { NEARESTMV, { LAST_FRAME, GOLDEN_FRAME } },
   { NEARESTMV, { BWDREF_FRAME, ALTREF_FRAME } },
 #endif  // CONFIG_EXT_COMP_REFS
@@ -380,6 +382,14 @@
   { NEW_NEWMV, { LAST_FRAME, LAST2_FRAME } },
   { ZERO_ZEROMV, { LAST_FRAME, LAST2_FRAME } },
 
+  { NEAR_NEARMV, { LAST_FRAME, LAST3_FRAME } },
+  { NEW_NEARESTMV, { LAST_FRAME, LAST3_FRAME } },
+  { NEAREST_NEWMV, { LAST_FRAME, LAST3_FRAME } },
+  { NEW_NEARMV, { LAST_FRAME, LAST3_FRAME } },
+  { NEAR_NEWMV, { LAST_FRAME, LAST3_FRAME } },
+  { NEW_NEWMV, { LAST_FRAME, LAST3_FRAME } },
+  { ZERO_ZEROMV, { LAST_FRAME, LAST3_FRAME } },
+
   { NEAR_NEARMV, { LAST_FRAME, GOLDEN_FRAME } },
   { NEW_NEARESTMV, { LAST_FRAME, GOLDEN_FRAME } },
   { NEAREST_NEWMV, { LAST_FRAME, GOLDEN_FRAME } },
@@ -424,6 +434,8 @@
 #if CONFIG_EXT_COMP_REFS
   { NEARMV, { LAST_FRAME, LAST2_FRAME } },
   { NEWMV, { LAST_FRAME, LAST2_FRAME } },
+  { NEARMV, { LAST_FRAME, LAST3_FRAME } },
+  { NEWMV, { LAST_FRAME, LAST3_FRAME } },
   { NEARMV, { LAST_FRAME, GOLDEN_FRAME } },
   { NEWMV, { LAST_FRAME, GOLDEN_FRAME } },
   { NEARMV, { BWDREF_FRAME, ALTREF_FRAME } },
@@ -446,6 +458,7 @@
 
 #if CONFIG_EXT_COMP_REFS
   { ZEROMV, { LAST_FRAME, LAST2_FRAME } },
+  { ZEROMV, { LAST_FRAME, LAST3_FRAME } },
   { ZEROMV, { LAST_FRAME, GOLDEN_FRAME } },
   { ZEROMV, { BWDREF_FRAME, ALTREF_FRAME } },
 #endif  // CONFIG_EXT_COMP_REFS
@@ -6054,62 +6067,26 @@
                       ref_costs_single[ALTREF_FRAME] = base_cost;
 
 #if CONFIG_EXT_REFS
-#if CONFIG_VAR_REFS
-      // Test need to explicitly code (L,L2,L3,G) vs (BWD,ALT) branch node in
-      // tree
-      if ((L_OR_L2(cm) || L3_OR_G(cm)) && BWD_OR_ALT(cm)) {
-#endif  // CONFIG_VAR_REFS
-        ref_costs_single[LAST_FRAME] += av1_cost_bit(ref_single_p1, 0);
-        ref_costs_single[LAST2_FRAME] += av1_cost_bit(ref_single_p1, 0);
-        ref_costs_single[LAST3_FRAME] += av1_cost_bit(ref_single_p1, 0);
-        ref_costs_single[GOLDEN_FRAME] += av1_cost_bit(ref_single_p1, 0);
-        ref_costs_single[BWDREF_FRAME] += av1_cost_bit(ref_single_p1, 1);
-        ref_costs_single[ALTREF_FRAME] += av1_cost_bit(ref_single_p1, 1);
-#if CONFIG_VAR_REFS
-      }
-#endif  // CONFIG_VAR_REFS
+      ref_costs_single[LAST_FRAME] += av1_cost_bit(ref_single_p1, 0);
+      ref_costs_single[LAST2_FRAME] += av1_cost_bit(ref_single_p1, 0);
+      ref_costs_single[LAST3_FRAME] += av1_cost_bit(ref_single_p1, 0);
+      ref_costs_single[GOLDEN_FRAME] += av1_cost_bit(ref_single_p1, 0);
+      ref_costs_single[BWDREF_FRAME] += av1_cost_bit(ref_single_p1, 1);
+      ref_costs_single[ALTREF_FRAME] += av1_cost_bit(ref_single_p1, 1);
 
-#if CONFIG_VAR_REFS
-      // Test need to explicitly code (L,L2) vs (L3,G) branch node in tree
-      if (L_OR_L2(cm) && L3_OR_G(cm)) {
-#endif  // CONFIG_VAR_REFS
-        ref_costs_single[LAST_FRAME] += av1_cost_bit(ref_single_p3, 0);
-        ref_costs_single[LAST2_FRAME] += av1_cost_bit(ref_single_p3, 0);
-        ref_costs_single[LAST3_FRAME] += av1_cost_bit(ref_single_p3, 1);
-        ref_costs_single[GOLDEN_FRAME] += av1_cost_bit(ref_single_p3, 1);
-#if CONFIG_VAR_REFS
-      }
-#endif  // CONFIG_VAR_REFS
+      ref_costs_single[LAST_FRAME] += av1_cost_bit(ref_single_p3, 0);
+      ref_costs_single[LAST2_FRAME] += av1_cost_bit(ref_single_p3, 0);
+      ref_costs_single[LAST3_FRAME] += av1_cost_bit(ref_single_p3, 1);
+      ref_costs_single[GOLDEN_FRAME] += av1_cost_bit(ref_single_p3, 1);
 
-#if CONFIG_VAR_REFS
-      // Test need to explicitly code (BWD) vs (ALT) branch node in tree
-      if (BWD_AND_ALT(cm)) {
-#endif  // CONFIG_VAR_REFS
-        ref_costs_single[BWDREF_FRAME] += av1_cost_bit(ref_single_p2, 0);
-        ref_costs_single[ALTREF_FRAME] += av1_cost_bit(ref_single_p2, 1);
-#if CONFIG_VAR_REFS
-      }
-#endif  // CONFIG_VAR_REFS
+      ref_costs_single[BWDREF_FRAME] += av1_cost_bit(ref_single_p2, 0);
+      ref_costs_single[ALTREF_FRAME] += av1_cost_bit(ref_single_p2, 1);
 
-#if CONFIG_VAR_REFS
-      // Test need to explicitly code (L) vs (L2) branch node in tree
-      if (L_AND_L2(cm)) {
-#endif  // CONFIG_VAR_REFS
-        ref_costs_single[LAST_FRAME] += av1_cost_bit(ref_single_p4, 0);
-        ref_costs_single[LAST2_FRAME] += av1_cost_bit(ref_single_p4, 1);
-#if CONFIG_VAR_REFS
-      }
-#endif  // CONFIG_VAR_REFS
+      ref_costs_single[LAST_FRAME] += av1_cost_bit(ref_single_p4, 0);
+      ref_costs_single[LAST2_FRAME] += av1_cost_bit(ref_single_p4, 1);
 
-#if CONFIG_VAR_REFS
-      // Test need to explicitly code (L3) vs (G) branch node in tree
-      if (L3_AND_G(cm)) {
-#endif  // CONFIG_VAR_REFS
-        ref_costs_single[LAST3_FRAME] += av1_cost_bit(ref_single_p5, 0);
-        ref_costs_single[GOLDEN_FRAME] += av1_cost_bit(ref_single_p5, 1);
-#if CONFIG_VAR_REFS
-      }
-#endif  // CONFIG_VAR_REFS
+      ref_costs_single[LAST3_FRAME] += av1_cost_bit(ref_single_p5, 0);
+      ref_costs_single[GOLDEN_FRAME] += av1_cost_bit(ref_single_p5, 1);
 #else   // !CONFIG_EXT_REFS
       ref_costs_single[LAST_FRAME] += av1_cost_bit(ref_single_p1, 0);
       ref_costs_single[GOLDEN_FRAME] += av1_cost_bit(ref_single_p1, 1);
@@ -6176,13 +6153,19 @@
 
       aom_prob uni_comp_ref_p = av1_get_pred_prob_uni_comp_ref_p(cm, xd);
       aom_prob uni_comp_ref_p1 = av1_get_pred_prob_uni_comp_ref_p1(cm, xd);
+      aom_prob uni_comp_ref_p2 = av1_get_pred_prob_uni_comp_ref_p2(cm, xd);
 
       ref_costs_comp[LAST_FRAME][LAST2_FRAME] =
           base_cost + av1_cost_bit(comp_ref_type_p, 0) +
           av1_cost_bit(uni_comp_ref_p, 0) + av1_cost_bit(uni_comp_ref_p1, 0);
+      ref_costs_comp[LAST_FRAME][LAST3_FRAME] =
+          base_cost + av1_cost_bit(comp_ref_type_p, 0) +
+          av1_cost_bit(uni_comp_ref_p, 0) + av1_cost_bit(uni_comp_ref_p1, 1) +
+          av1_cost_bit(uni_comp_ref_p2, 0);
       ref_costs_comp[LAST_FRAME][GOLDEN_FRAME] =
           base_cost + av1_cost_bit(comp_ref_type_p, 0) +
-          av1_cost_bit(uni_comp_ref_p, 0) + av1_cost_bit(uni_comp_ref_p1, 1);
+          av1_cost_bit(uni_comp_ref_p, 0) + av1_cost_bit(uni_comp_ref_p1, 1) +
+          av1_cost_bit(uni_comp_ref_p2, 1);
 
       ref_costs_comp[BWDREF_FRAME][ALTREF_FRAME] =
           base_cost + av1_cost_bit(comp_ref_type_p, 0) +
@@ -6201,49 +6184,21 @@
 #endif  // CONFIG_EXT_REFS
 
 #if CONFIG_EXT_REFS
-#if CONFIG_VAR_REFS
-      // Test need to explicitly code (L,L2) vs (L3,G) branch node in tree
-      if (L_OR_L2(cm) && L3_OR_G(cm)) {
-#endif  // CONFIG_VAR_REFS
-        ref_costs_comp[LAST_FRAME] += av1_cost_bit(ref_comp_p, 0);
-        ref_costs_comp[LAST2_FRAME] += av1_cost_bit(ref_comp_p, 0);
-        ref_costs_comp[LAST3_FRAME] += av1_cost_bit(ref_comp_p, 1);
-        ref_costs_comp[GOLDEN_FRAME] += av1_cost_bit(ref_comp_p, 1);
-#if CONFIG_VAR_REFS
-      }
-#endif  // CONFIG_VAR_REFS
+      ref_costs_comp[LAST_FRAME] += av1_cost_bit(ref_comp_p, 0);
+      ref_costs_comp[LAST2_FRAME] += av1_cost_bit(ref_comp_p, 0);
+      ref_costs_comp[LAST3_FRAME] += av1_cost_bit(ref_comp_p, 1);
+      ref_costs_comp[GOLDEN_FRAME] += av1_cost_bit(ref_comp_p, 1);
 
-#if CONFIG_VAR_REFS
-      // Test need to explicitly code (L) vs (L2) branch node in tree
-      if (L_AND_L2(cm)) {
-#endif  // CONFIG_VAR_REFS
-        ref_costs_comp[LAST_FRAME] += av1_cost_bit(ref_comp_p1, 1);
-        ref_costs_comp[LAST2_FRAME] += av1_cost_bit(ref_comp_p1, 0);
-#if CONFIG_VAR_REFS
-      }
-#endif  // CONFIG_VAR_REFS
+      ref_costs_comp[LAST_FRAME] += av1_cost_bit(ref_comp_p1, 1);
+      ref_costs_comp[LAST2_FRAME] += av1_cost_bit(ref_comp_p1, 0);
 
-#if CONFIG_VAR_REFS
-      // Test need to explicitly code (L3) vs (G) branch node in tree
-      if (L3_AND_G(cm)) {
-#endif  // CONFIG_VAR_REFS
-        ref_costs_comp[LAST3_FRAME] += av1_cost_bit(ref_comp_p2, 0);
-        ref_costs_comp[GOLDEN_FRAME] += av1_cost_bit(ref_comp_p2, 1);
-#if CONFIG_VAR_REFS
-      }
-#endif  // CONFIG_VAR_REFS
+      ref_costs_comp[LAST3_FRAME] += av1_cost_bit(ref_comp_p2, 0);
+      ref_costs_comp[GOLDEN_FRAME] += av1_cost_bit(ref_comp_p2, 1);
 
-// NOTE(zoeliu): BWDREF and ALTREF each add an extra cost by coding 1
-//               more bit.
-#if CONFIG_VAR_REFS
-      // Test need to explicitly code (BWD) vs (ALT) branch node in tree
-      if (BWD_AND_ALT(cm)) {
-#endif  // CONFIG_VAR_REFS
-        ref_costs_comp[BWDREF_FRAME] += av1_cost_bit(bwdref_comp_p, 0);
-        ref_costs_comp[ALTREF_FRAME] += av1_cost_bit(bwdref_comp_p, 1);
-#if CONFIG_VAR_REFS
-      }
-#endif  // CONFIG_VAR_REFS
+      // NOTE(zoeliu): BWDREF and ALTREF each add an extra cost by coding 1
+      //               more bit.
+      ref_costs_comp[BWDREF_FRAME] += av1_cost_bit(bwdref_comp_p, 0);
+      ref_costs_comp[ALTREF_FRAME] += av1_cost_bit(bwdref_comp_p, 1);
 #else   // !CONFIG_EXT_REFS
       ref_costs_comp[LAST_FRAME] += av1_cost_bit(ref_comp_p, 0);
       ref_costs_comp[GOLDEN_FRAME] += av1_cost_bit(ref_comp_p, 1);
@@ -6257,6 +6212,7 @@
         ref_costs_comp[ref0][ALTREF_FRAME] = 512;
       }
       ref_costs_comp[LAST_FRAME][LAST2_FRAME] = 512;
+      ref_costs_comp[LAST_FRAME][LAST3_FRAME] = 512;
       ref_costs_comp[LAST_FRAME][GOLDEN_FRAME] = 512;
       ref_costs_comp[BWDREF_FRAME][ALTREF_FRAME] = 512;
 #else  // !CONFIG_EXT_COMP_REFS
diff --git a/configure b/configure
index 01869ea..6f7a1fe 100755
--- a/configure
+++ b/configure
@@ -543,6 +543,8 @@
     enabled warped_motion && disable_feature ncobmc_adapt_weight
     enabled ncobmc_adapt_weight && enable_feature motion_var
     enabled bgsprite && enable_feature global_motion
+    enabled ext_comp_refs && enable_feature var_refs
+    enabled ext_comp_refs && disable_feature one_sided_compound
 
     if ! enabled delta_q && enabled ext_delta_q; then
       log_echo "ext_delta_q requires delta_q, so disabling ext_delta_q"