Port CONFIG_NEW_INTER_MODES to research branch

AV1 has symbols NEARESTMV and NEARMV to differentiate
between MV0 (nearest) and MV1/MV2/MV3 (near). This
distinction was inherited from VP9, which only had two
motion vectors and only used two symbols. This change
cleans up the syntax so a single mode, NEARMV, can be
used to identify any motion vector. This change is
extended to cover the compound modes. Moreover, the
NEWMV mode, which could only access 0, 1, 2, is
extended and can access any motion vector.

Original work by siroh@ on the experimental branch

Change-Id: I99b162b3d7657a3b6c0bd070364a59a0815b302e
diff --git a/av1/common/av1_loopfilter.c b/av1/common/av1_loopfilter.c
index f29a8b2..46bad85 100644
--- a/av1/common/av1_loopfilter.c
+++ b/av1/common/av1_loopfilter.c
@@ -31,11 +31,19 @@
 static const int delta_lf_id_lut[MAX_MB_PLANE][2] = { { 0, 1 },
                                                       { 2, 2 },
                                                       { 3, 3 } };
+#if CONFIG_NEW_INTER_MODES
+static const int mode_lf_lut[] = {
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // INTRA_MODES
+  1, 0, 1,                                // INTER_MODES (GLOBALMV == 0)
+  1, 1, 1, 0, 1,  // INTER_COMPOUND_MODES (GLOBAL_GLOBALMV == 0)
+};
+#else
 static const int mode_lf_lut[] = {
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // INTRA_MODES
   1, 1, 0, 1,                             // INTER_SINGLE_MODES (GLOBALMV == 0)
   1, 1, 1, 1, 1, 1, 0, 1  // INTER_COMPOUND_MODES (GLOBAL_GLOBALMV == 0)
 };
+#endif  // CONFIG_NEW_INTER_MODES
 
 static void update_sharpness(loop_filter_info_n *lfi, int sharpness_lvl) {
   int lvl;
diff --git a/av1/common/blockd.h b/av1/common/blockd.h
index 858ae92..6d68f14 100644
--- a/av1/common/blockd.h
+++ b/av1/common/blockd.h
@@ -91,18 +91,24 @@
     SMOOTH_V_PRED,  // SMOOTH_V_PRED
     SMOOTH_H_PRED,  // SMOOTH_H_PRED
     PAETH_PRED,     // PAETH_PRED
-    NEARESTMV,      // NEARESTMV
-    NEARMV,         // NEARMV
-    GLOBALMV,       // GLOBALMV
-    NEWMV,          // NEWMV
-    NEARESTMV,      // NEAREST_NEARESTMV
-    NEARMV,         // NEAR_NEARMV
-    NEARESTMV,      // NEAREST_NEWMV
-    NEWMV,          // NEW_NEARESTMV
-    NEARMV,         // NEAR_NEWMV
-    NEWMV,          // NEW_NEARMV
-    GLOBALMV,       // GLOBAL_GLOBALMV
-    NEWMV,          // NEW_NEWMV
+#if !CONFIG_NEW_INTER_MODES
+    NEARESTMV,  // NEARESTMV
+#endif          // !CONFIG_NEW_INTER_MODES
+    NEARMV,     // NEARMV
+    GLOBALMV,   // GLOBALMV
+    NEWMV,      // NEWMV
+#if !CONFIG_NEW_INTER_MODES
+    NEARESTMV,  // NEAREST_NEARESTMV
+#endif          // !CONFIG_NEW_INTER_MODES
+    NEARMV,     // NEAR_NEARMV
+#if !CONFIG_NEW_INTER_MODES
+    NEARESTMV,  // NEAREST_NEWMV
+    NEWMV,      // NEW_NEARESTMV
+#endif          // !CONFIG_NEW_INTER_MODES
+    NEARMV,     // NEAR_NEWMV
+    NEWMV,      // NEW_NEARMV
+    GLOBALMV,   // GLOBAL_GLOBALMV
+    NEWMV,      // NEW_NEWMV
   };
   assert(NELEMENTS(lut) == MB_MODE_COUNT);
   assert(is_inter_compound_mode(mode) || is_inter_singleref_mode(mode));
@@ -124,18 +130,24 @@
     MB_MODE_COUNT,  // SMOOTH_V_PRED
     MB_MODE_COUNT,  // SMOOTH_H_PRED
     MB_MODE_COUNT,  // PAETH_PRED
+#if !CONFIG_NEW_INTER_MODES
     MB_MODE_COUNT,  // NEARESTMV
+#endif              // !CONFIG_NEW_INTER_MODES
     MB_MODE_COUNT,  // NEARMV
     MB_MODE_COUNT,  // GLOBALMV
     MB_MODE_COUNT,  // NEWMV
-    NEARESTMV,      // NEAREST_NEARESTMV
-    NEARMV,         // NEAR_NEARMV
-    NEWMV,          // NEAREST_NEWMV
-    NEARESTMV,      // NEW_NEARESTMV
-    NEWMV,          // NEAR_NEWMV
-    NEARMV,         // NEW_NEARMV
-    GLOBALMV,       // GLOBAL_GLOBALMV
-    NEWMV,          // NEW_NEWMV
+#if !CONFIG_NEW_INTER_MODES
+    NEARESTMV,  // NEAREST_NEARESTMV
+#endif          // !CONFIG_NEW_INTER_MODES
+    NEARMV,     // NEAR_NEARMV
+#if !CONFIG_NEW_INTER_MODES
+    NEWMV,      // NEAREST_NEWMV
+    NEARESTMV,  // NEW_NEARESTMV
+#endif          // !CONFIG_NEW_INTER_MODES
+    NEWMV,      // NEAR_NEWMV
+    NEARMV,     // NEW_NEARMV
+    GLOBALMV,   // GLOBAL_GLOBALMV
+    NEWMV,      // NEW_NEWMV
   };
   assert(NELEMENTS(lut) == MB_MODE_COUNT);
   assert(is_inter_compound_mode(mode));
@@ -147,10 +159,20 @@
           mode == NEW_NEARMV);
 }
 
+#if CONFIG_NEW_INTER_MODES
+static INLINE int have_newmv_in_inter_mode(PREDICTION_MODE mode) {
+  return (mode == NEWMV || mode == NEW_NEWMV || mode == NEAR_NEWMV ||
+          mode == NEW_NEARMV);
+}
+static INLINE int have_drl_index(PREDICTION_MODE mode) {
+  return have_nearmv_in_inter_mode(mode) || have_newmv_in_inter_mode(mode);
+}
+#else
 static INLINE int have_newmv_in_inter_mode(PREDICTION_MODE mode) {
   return (mode == NEWMV || mode == NEW_NEWMV || mode == NEAREST_NEWMV ||
           mode == NEW_NEARESTMV || mode == NEAR_NEWMV || mode == NEW_NEARMV);
 }
+#endif  // CONFIG_NEW_INTER_MODES
 
 static INLINE int is_masked_compound_type(COMPOUND_TYPE type) {
   return (type == COMPOUND_WEDGE || type == COMPOUND_DIFFWTD);
@@ -287,7 +309,11 @@
 #else
   uint8_t use_intrabc : 1;
 #endif
+#if CONFIG_NEW_INTER_MODES && MAX_DRL_BITS > 3
+  uint8_t ref_mv_idx : 3;
+#else
   uint8_t ref_mv_idx : 2;
+#endif  // CONFIG_NEW_INTER_MODES && MAX_DRL_BITS > 3
   // Indicate if masked compound is used(1) or not(0).
   uint8_t comp_group_idx : 1;
   int8_t cdef_strength : 4;
diff --git a/av1/common/entropy.c b/av1/common/entropy.c
index 428a1a3..4f0c0bd 100644
--- a/av1/common/entropy.c
+++ b/av1/common/entropy.c
@@ -99,8 +99,14 @@
   RESET_CDF_COUNTER(fc->coeff_br_cdf, BR_CDF_SIZE);
   RESET_CDF_COUNTER(fc->newmv_cdf, 2);
   RESET_CDF_COUNTER(fc->zeromv_cdf, 2);
-  RESET_CDF_COUNTER(fc->refmv_cdf, 2);
+#if CONFIG_NEW_INTER_MODES
+  RESET_CDF_COUNTER(fc->drl_cdf[0], 2);
+  RESET_CDF_COUNTER(fc->drl_cdf[1], 2);
+  RESET_CDF_COUNTER(fc->drl_cdf[2], 2);
+#else
   RESET_CDF_COUNTER(fc->drl_cdf, 2);
+  RESET_CDF_COUNTER(fc->refmv_cdf, 2);
+#endif  // CONFIG_NEW_INTER_MODES
   RESET_CDF_COUNTER(fc->inter_compound_mode_cdf, INTER_COMPOUND_MODES);
   RESET_CDF_COUNTER(fc->compound_type_cdf, MASKED_COMPOUND_TYPES);
   RESET_CDF_COUNTER(fc->wedge_idx_cdf, 16);
diff --git a/av1/common/entropymode.c b/av1/common/entropymode.c
index 74e7204..d9b23a9 100644
--- a/av1/common/entropymode.c
+++ b/av1/common/entropymode.c
@@ -562,7 +562,41 @@
       { AOM_CDF3(31022, 32009) }, { AOM_CDF3(2963, 32093) },
       { AOM_CDF3(601, 943) },     { AOM_CDF3(14969, 21398) }
     };
+#if CONFIG_NEW_INTER_MODES
+static const aom_cdf_prob default_newmv_cdf[NEWMV_MODE_CONTEXTS][CDF_SIZE(
+    2)] = { { AOM_CDF2(18789) }, { AOM_CDF2(19230) }, { AOM_CDF2(19464) },
+            { AOM_CDF2(9445) },  { AOM_CDF2(15773) }, { AOM_CDF2(5513) } };
+static const aom_cdf_prob default_zeromv_cdf[GLOBALMV_MODE_CONTEXTS][CDF_SIZE(
+    2)] = { { AOM_CDF2(6154) }, { AOM_CDF2(2663) } };
 
+static const aom_cdf_prob default_drl0_cdf[DRL_MODE_CONTEXTS][CDF_SIZE(2)] = {
+  { AOM_CDF2(15946) },
+  { AOM_CDF2(24871) },
+  { AOM_CDF2(16015) },
+};
+
+static const aom_cdf_prob default_drl1_cdf[DRL_MODE_CONTEXTS][CDF_SIZE(2)] = {
+  { AOM_CDF2(15946) },
+  { AOM_CDF2(24871) },
+  { AOM_CDF2(16015) },
+};
+
+static const aom_cdf_prob default_drl2_cdf[DRL_MODE_CONTEXTS][CDF_SIZE(2)] = {
+  { AOM_CDF2(15946) },
+  { AOM_CDF2(24871) },
+  { AOM_CDF2(16015) },
+};
+static const aom_cdf_prob
+    default_inter_compound_mode_cdf[INTER_COMPOUND_MODE_CONTEXTS][CDF_SIZE(
+        INTER_COMPOUND_MODES)] = { { AOM_CDF5(13823, 17323, 20666, 26891) },
+                                   { AOM_CDF5(19452, 22435, 25131, 28724) },
+                                   { AOM_CDF5(20221, 22977, 25387, 28436) },
+                                   { AOM_CDF5(16984, 21356, 25736, 26422) },
+                                   { AOM_CDF5(23325, 25708, 28258, 30758) },
+                                   { AOM_CDF5(17454, 21499, 25168, 26046) },
+                                   { AOM_CDF5(24273, 26536, 28704, 30592) },
+                                   { AOM_CDF5(23214, 25998, 28442, 29330) } };
+#else
 static const aom_cdf_prob default_newmv_cdf[NEWMV_MODE_CONTEXTS][CDF_SIZE(
     2)] = { { AOM_CDF2(24035) }, { AOM_CDF2(16630) }, { AOM_CDF2(15339) },
             { AOM_CDF2(8386) },  { AOM_CDF2(12222) }, { AOM_CDF2(4676) } };
@@ -590,7 +624,7 @@
       { AOM_CDF8(17125, 24273, 25814, 27492, 28214, 28704, 30592) },
       { AOM_CDF8(13046, 23214, 24505, 25942, 27435, 28442, 29330) }
     };
-
+#endif  // CONFIG_NEW_INTER_MODES
 static const aom_cdf_prob default_interintra_cdf[BLOCK_SIZE_GROUPS][CDF_SIZE(
     2)] = { { AOM_CDF2(16384) },
             { AOM_CDF2(26887) },
@@ -1254,8 +1288,14 @@
   av1_copy(fc->comp_group_idx_cdf, default_comp_group_idx_cdfs);
   av1_copy(fc->newmv_cdf, default_newmv_cdf);
   av1_copy(fc->zeromv_cdf, default_zeromv_cdf);
+#if CONFIG_NEW_INTER_MODES
+  av1_copy(fc->drl_cdf[0], default_drl0_cdf);
+  av1_copy(fc->drl_cdf[1], default_drl1_cdf);
+  av1_copy(fc->drl_cdf[2], default_drl2_cdf);
+#else
   av1_copy(fc->refmv_cdf, default_refmv_cdf);
   av1_copy(fc->drl_cdf, default_drl_cdf);
+#endif  // CONFIG_NEW_INTER_MODES
   av1_copy(fc->motion_mode_cdf, default_motion_mode_cdf);
   av1_copy(fc->obmc_cdf, default_obmc_cdf);
   av1_copy(fc->inter_compound_mode_cdf, default_inter_compound_mode_cdf);
diff --git a/av1/common/entropymode.h b/av1/common/entropymode.h
index 6d621ed..fb04335 100644
--- a/av1/common/entropymode.h
+++ b/av1/common/entropymode.h
@@ -26,9 +26,13 @@
 
 #define TX_SIZE_CONTEXTS 3
 
+#if CONFIG_NEW_INTER_MODES
+#define INTER_OFFSET(mode) ((mode)-NEARMV)
+#define INTER_COMPOUND_OFFSET(mode) (uint8_t)((mode)-NEAR_NEARMV)
+#else
 #define INTER_OFFSET(mode) ((mode)-NEARESTMV)
 #define INTER_COMPOUND_OFFSET(mode) (uint8_t)((mode)-NEAREST_NEARESTMV)
-
+#endif  // CONFIG_NEW_INTER_MODES
 // Number of possible contexts for a color index.
 // As can be seen from av1_get_palette_color_index_context(), the possible
 // contexts are (2,0,0), (2,2,1), (3,2,0), (4,1,0), (5,0,0). These are mapped to
@@ -86,8 +90,12 @@
 
   aom_cdf_prob newmv_cdf[NEWMV_MODE_CONTEXTS][CDF_SIZE(2)];
   aom_cdf_prob zeromv_cdf[GLOBALMV_MODE_CONTEXTS][CDF_SIZE(2)];
-  aom_cdf_prob refmv_cdf[REFMV_MODE_CONTEXTS][CDF_SIZE(2)];
+#if CONFIG_NEW_INTER_MODES
+  aom_cdf_prob drl_cdf[3][DRL_MODE_CONTEXTS][CDF_SIZE(2)];
+#else
   aom_cdf_prob drl_cdf[DRL_MODE_CONTEXTS][CDF_SIZE(2)];
+  aom_cdf_prob refmv_cdf[REFMV_MODE_CONTEXTS][CDF_SIZE(2)];
+#endif  // CONFIG_NEW_INTER_MODES
 
   aom_cdf_prob inter_compound_mode_cdf[INTER_COMPOUND_MODE_CONTEXTS]
                                       [CDF_SIZE(INTER_COMPOUND_MODES)];
diff --git a/av1/common/enums.h b/av1/common/enums.h
index 47cf8b0..25c70b7 100644
--- a/av1/common/enums.h
+++ b/av1/common/enums.h
@@ -428,32 +428,55 @@
   SMOOTH_V_PRED,  // Vertical interpolation
   SMOOTH_H_PRED,  // Horizontal interpolation
   PAETH_PRED,     // Predict from the direction of smallest gradient
+#if !CONFIG_NEW_INTER_MODES
   NEARESTMV,
+#endif  // !CONFIG_NEW_INTER_MODES
   NEARMV,
   GLOBALMV,
   NEWMV,
-  // Compound ref compound modes
+// Compound ref compound modes
+#if !CONFIG_NEW_INTER_MODES
   NEAREST_NEARESTMV,
+#endif  // !CONFIG_NEW_INTER_MODES
   NEAR_NEARMV,
+#if !CONFIG_NEW_INTER_MODES
   NEAREST_NEWMV,
   NEW_NEARESTMV,
+#endif  // !CONFIG_NEW_INTER_MODES
   NEAR_NEWMV,
   NEW_NEARMV,
   GLOBAL_GLOBALMV,
   NEW_NEWMV,
   MB_MODE_COUNT,
   INTRA_MODE_START = DC_PRED,
+#if CONFIG_NEW_INTER_MODES
+  INTRA_MODE_END = NEARMV,
+#else
   INTRA_MODE_END = NEARESTMV,
+#endif  // CONFIG_NEW_INTER_MODES
   DIR_MODE_START = V_PRED,
   DIR_MODE_END = D67_PRED + 1,
   INTRA_MODE_NUM = INTRA_MODE_END - INTRA_MODE_START,
+#if CONFIG_NEW_INTER_MODES
+  SINGLE_INTER_MODE_START = NEARMV,
+  SINGLE_INTER_MODE_END = NEAR_NEARMV,
+#else
   SINGLE_INTER_MODE_START = NEARESTMV,
   SINGLE_INTER_MODE_END = NEAREST_NEARESTMV,
+#endif  // CONFIG_NEW_INTER_MODES
   SINGLE_INTER_MODE_NUM = SINGLE_INTER_MODE_END - SINGLE_INTER_MODE_START,
+#if CONFIG_NEW_INTER_MODES
+  COMP_INTER_MODE_START = NEAR_NEARMV,
+#else
   COMP_INTER_MODE_START = NEAREST_NEARESTMV,
+#endif  // CONFIG_NEW_INTER_MODES
   COMP_INTER_MODE_END = MB_MODE_COUNT,
   COMP_INTER_MODE_NUM = COMP_INTER_MODE_END - COMP_INTER_MODE_START,
+#if CONFIG_NEW_INTER_MODES
+  INTER_MODE_START = NEARMV,
+#else
   INTER_MODE_START = NEARESTMV,
+#endif  // CONFIG_NEW_INTER_MODES
   INTER_MODE_END = MB_MODE_COUNT,
   INTRA_MODES = PAETH_PRED + 1,  // PAETH_PRED has to be the last intra mode.
   INTRA_INVALID = MB_MODE_COUNT  // For uv_mode in inter blocks
@@ -562,8 +585,13 @@
 #define ANGLE_DELTA_VALUE_ORIP (MAX_ANGLE_DELTA + 1)
 #endif
 
-#define INTER_SINGLE_MODES (1 + NEWMV - NEARESTMV)
+#if CONFIG_NEW_INTER_MODES
+#define INTER_MODES (1 + NEWMV - NEARMV)
+#define INTER_COMPOUND_MODES (1 + NEW_NEWMV - NEAR_NEARMV)
+#else
+#define INTER_MODES (1 + NEWMV - NEARESTMV)
 #define INTER_COMPOUND_MODES (1 + NEW_NEWMV - NEAREST_NEARESTMV)
+#endif  // CONFIG_NEW_INTER_MODES
 
 #define SKIP_CONTEXTS 3
 #define SKIP_MODE_CONTEXTS 3
@@ -575,7 +603,14 @@
 
 #define NEWMV_MODE_CONTEXTS 6
 #define GLOBALMV_MODE_CONTEXTS 2
+
+#if CONFIG_NEW_INTER_MODES
+#define MAX_DRL_BITS 3
+#else
 #define REFMV_MODE_CONTEXTS 6
+#define MAX_DRL_BITS 2
+#endif  // CONFIG_NEW_INTER_MODES
+
 #define DRL_MODE_CONTEXTS 3
 
 #define GLOBALMV_OFFSET 3
@@ -601,7 +636,16 @@
 #define MAX_MV_REF_CANDIDATES 2
 
 #define MAX_REF_MV_STACK_SIZE 8
+#if MAX_DRL_BITS + 1 > MAX_REF_MV_STACK_SIZE
+#error "MAX_DRL_BITS too high"
+#endif
+
+#if CONFIG_NEW_INTER_MODES
+#define USABLE_REF_MV_STACK_SIZE (MAX_DRL_BITS + 1)
+#else
 #define USABLE_REF_MV_STACK_SIZE 4
+#endif  // CONFIG_NEW_INTER_MODES
+
 #define REF_CAT_LEVEL 640
 
 #define INTRA_INTER_CONTEXTS 4
diff --git a/av1/common/mvref_common.c b/av1/common/mvref_common.c
index 61bcac5..62f86b4 100644
--- a/av1/common/mvref_common.c
+++ b/av1/common/mvref_common.c
@@ -808,6 +808,23 @@
         mv_ref_list[idx].as_int = ref_mv_stack[idx].this_mv.as_int;
       }
     }
+#if CONFIG_NEW_INTER_MODES
+    // If there is extra space in the stack, copy the GLOBALMV vector into it.
+    // This also guarantees the existence of at least one vector to search.
+    if (*refmv_count < MAX_REF_MV_STACK_SIZE) {
+      int stack_idx;
+      for (stack_idx = 0; stack_idx < *refmv_count; ++stack_idx) {
+        const int_mv stack_mv = ref_mv_stack[stack_idx].this_mv;
+        if (gm_mv_candidates[0].as_int == stack_mv.as_int) break;
+      }
+      if (stack_idx == *refmv_count) {
+        ref_mv_stack[*refmv_count].this_mv.as_int = gm_mv_candidates[0].as_int;
+        ref_mv_stack[*refmv_count].comp_mv.as_int = gm_mv_candidates[1].as_int;
+        ref_mv_weight[*refmv_count] = REF_CAT_LEVEL;
+        (*refmv_count)++;
+      }
+    }
+#endif  // CONFIG_NEW_INTER_MODES
   }
 }
 
@@ -1479,6 +1496,19 @@
   remapped_ref_idx[frame_idx] = ref_info->map_idx;
 }
 
+#if CONFIG_NEW_INTER_MODES
+aom_cdf_prob *av1_get_drl_cdf(FRAME_CONTEXT *ec_ctx,
+                              const uint16_t *ref_mv_weight, int ref_idx) {
+  assert(ref_idx >= 0 && ref_idx < MAX_DRL_BITS + 1);
+  const int ctx = av1_drl_ctx(ref_mv_weight, ref_idx);
+  switch (ref_idx) {
+    case 0: return ec_ctx->drl_cdf[0][ctx];
+    case 1: return ec_ctx->drl_cdf[1][ctx];
+    default: return ec_ctx->drl_cdf[2][ctx];
+  }
+}
+#endif  // CONFIG_NEW_INTER_MODES
+
 void av1_set_frame_refs(AV1_COMMON *const cm, int *remapped_ref_idx,
                         int lst_map_idx, int gld_map_idx) {
   int lst_frame_sort_idx = -1;
diff --git a/av1/common/mvref_common.h b/av1/common/mvref_common.h
index 18f4259..594e6c6 100644
--- a/av1/common/mvref_common.h
+++ b/av1/common/mvref_common.h
@@ -183,6 +183,10 @@
 }
 
 static INLINE uint8_t av1_drl_ctx(const uint16_t *ref_mv_weight, int ref_idx) {
+#if CONFIG_NEW_INTER_MODES
+  assert(ref_idx >= 0 && ref_idx < MAX_DRL_BITS + 1);
+#endif  // CONFIG_NEW_INTER_MODES
+
   if (ref_mv_weight[ref_idx] >= REF_CAT_LEVEL &&
       ref_mv_weight[ref_idx + 1] >= REF_CAT_LEVEL)
     return 0;
@@ -198,6 +202,11 @@
   return 0;
 }
 
+#if CONFIG_NEW_INTER_MODES
+aom_cdf_prob *av1_get_drl_cdf(FRAME_CONTEXT *ec_ctx,
+                              const uint16_t *ref_mv_weight, int ref_idx);
+#endif  // CONFIG_NEW_INTER_MODES
+
 void av1_setup_frame_buf_refs(AV1_COMMON *cm);
 void av1_setup_frame_sign_bias(AV1_COMMON *cm);
 void av1_setup_skip_mode_allowed(AV1_COMMON *cm);
diff --git a/av1/decoder/decodemv.c b/av1/decoder/decodemv.c
index 21af700..70c54f8 100644
--- a/av1/decoder/decodemv.c
+++ b/av1/decoder/decodemv.c
@@ -208,7 +208,18 @@
 static PREDICTION_MODE read_inter_mode(FRAME_CONTEXT *ec_ctx, aom_reader *r,
                                        int16_t ctx) {
   int16_t mode_ctx = ctx & NEWMV_CTX_MASK;
+#if CONFIG_NEW_INTER_MODES
+  // TODO(siroh): For some frames, the DRL will be "empty."
+  // Under NEW_INTER_MODES, the frame GMV will be inserted to fix this.
+  // Under the old process, get_this_mv inserts the frame GMV on-the-fly.
+  // When this situation happens there's no actual need to signal the next
+  // bit, because it's either NEARMV 0 referencing the GMV or GLOBAL referencing
+  // the GMV.
+  // Implement this for NEW_INTER_MODES, possibly using a new context.
+  int is_newmv, is_zeromv;
+#else
   int is_newmv, is_zeromv, is_refmv;
+#endif  // CONFIG_NEW_INTER_MODES
   is_newmv = aom_read_symbol(r, ec_ctx->newmv_cdf[mode_ctx], 2, ACCT_STR) == 0;
   if (is_newmv) return NEWMV;
 
@@ -217,21 +228,43 @@
       aom_read_symbol(r, ec_ctx->zeromv_cdf[mode_ctx], 2, ACCT_STR) == 0;
   if (is_zeromv) return GLOBALMV;
 
+#if CONFIG_NEW_INTER_MODES
+  return NEARMV;
+#else
   mode_ctx = (ctx >> REFMV_OFFSET) & REFMV_CTX_MASK;
   is_refmv = aom_read_symbol(r, ec_ctx->refmv_cdf[mode_ctx], 2, ACCT_STR) == 0;
   if (is_refmv)
     return NEARESTMV;
   else
     return NEARMV;
+#endif  // CONFIG_NEW_INTER_MODES
 }
 
+#if CONFIG_NEW_INTER_MODES
+static void read_drl_idx(FRAME_CONTEXT *ec_ctx, DecoderCodingBlock *dcb,
+                         MB_MODE_INFO *mbmi, aom_reader *r) {
+  MACROBLOCKD *const xd = &dcb->xd;
+  uint8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
+  mbmi->ref_mv_idx = 0;
+  assert(!mbmi->skip_mode);
+  const int range = AOMMIN(dcb->ref_mv_count[ref_frame_type] - 1, MAX_DRL_BITS);
+  for (int idx = 0; idx < range; ++idx) {
+    aom_cdf_prob *drl_cdf =
+        av1_get_drl_cdf(ec_ctx, xd->weight[ref_frame_type], idx);
+    int drl_idx = aom_read_symbol(r, drl_cdf, 2, ACCT_STR);
+    mbmi->ref_mv_idx = idx + drl_idx;
+    if (!drl_idx) break;
+  }
+  assert(mbmi->ref_mv_idx < MAX_DRL_BITS + 1);
+}
+#else
 static void read_drl_idx(FRAME_CONTEXT *ec_ctx, DecoderCodingBlock *dcb,
                          MB_MODE_INFO *mbmi, aom_reader *r) {
   MACROBLOCKD *const xd = &dcb->xd;
   uint8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
   mbmi->ref_mv_idx = 0;
   if (mbmi->mode == NEWMV || mbmi->mode == NEW_NEWMV) {
-    for (int idx = 0; idx < 2; ++idx) {
+    for (int idx = 0; idx < MAX_DRL_BITS; ++idx) {
       if (dcb->ref_mv_count[ref_frame_type] > idx + 1) {
         uint8_t drl_ctx = av1_drl_ctx(xd->weight[ref_frame_type], idx);
         int drl_idx = aom_read_symbol(r, ec_ctx->drl_cdf[drl_ctx], 2, ACCT_STR);
@@ -244,7 +277,7 @@
     // Offset the NEARESTMV mode.
     // TODO(jingning): Unify the two syntax decoding loops after the NEARESTMV
     // mode is factored in.
-    for (int idx = 1; idx < 3; ++idx) {
+    for (int idx = 1; idx < MAX_DRL_BITS + 1; ++idx) {
       if (dcb->ref_mv_count[ref_frame_type] > idx + 1) {
         uint8_t drl_ctx = av1_drl_ctx(xd->weight[ref_frame_type], idx);
         int drl_idx = aom_read_symbol(r, ec_ctx->drl_cdf[drl_ctx], 2, ACCT_STR);
@@ -254,6 +287,7 @@
     }
   }
 }
+#endif  // CONFIG_NEW_INTER_MODES
 
 static MOTION_MODE read_motion_mode(AV1_COMMON *cm, MACROBLOCKD *xd,
                                     MB_MODE_INFO *mbmi, aom_reader *r) {
@@ -294,8 +328,13 @@
   const int mode =
       aom_read_symbol(r, xd->tile_ctx->inter_compound_mode_cdf[ctx],
                       INTER_COMPOUND_MODES, ACCT_STR);
+#if CONFIG_NEW_INTER_MODES
+  assert(is_inter_compound_mode(NEAR_NEARMV + mode));
+  return NEAR_NEARMV + mode;
+#else
   assert(is_inter_compound_mode(NEAREST_NEARESTMV + mode));
   return NEAREST_NEARESTMV + mode;
+#endif  // CONFIG_NEW_INTER_MODES
 }
 
 int av1_neg_deinterleave(int diff, int ref, int max) {
@@ -1230,7 +1269,6 @@
   MV diff = kZeroMv;
   const MV_JOINT_TYPE joint_type =
       (MV_JOINT_TYPE)aom_read_symbol(r, ctx->joints_cdf, MV_JOINTS, ACCT_STR);
-
   if (mv_joint_vertical(joint_type))
     diff.row = read_mv_component(r, &ctx->comps[0], precision > MV_SUBPEL_NONE,
                                  precision > MV_SUBPEL_LOW_PRECISION);
@@ -1558,6 +1596,10 @@
                             int_mv ref_mv[2], int_mv nearest_mv[2],
                             int_mv near_mv[2], int is_compound, int allow_hp,
                             aom_reader *r) {
+#if CONFIG_NEW_INTER_MODES
+  (void)nearest_mv;
+#endif  // CONFIG_NEW_INTER_MODES
+
   FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
   MB_MODE_INFO *mbmi = xd->mi[0];
 #if CONFIG_SDP
@@ -1575,10 +1617,12 @@
       read_mv(r, &mv[0].as_mv, &ref_mv[0].as_mv, nmvc, allow_hp);
       break;
     }
+#if !CONFIG_NEW_INTER_MODES
     case NEARESTMV: {
       mv[0].as_int = nearest_mv[0].as_int;
       break;
     }
+#endif  // !CONFIG_NEW_INTER_MODES
     case NEARMV: {
       mv[0].as_int = near_mv[0].as_int;
       break;
@@ -1599,18 +1643,21 @@
       }
       break;
     }
+#if !CONFIG_NEW_INTER_MODES
     case NEAREST_NEARESTMV: {
       assert(is_compound);
       mv[0].as_int = nearest_mv[0].as_int;
       mv[1].as_int = nearest_mv[1].as_int;
       break;
     }
+#endif  // !CONFIG_NEW_INTER_MODES
     case NEAR_NEARMV: {
       assert(is_compound);
       mv[0].as_int = near_mv[0].as_int;
       mv[1].as_int = near_mv[1].as_int;
       break;
     }
+#if !CONFIG_NEW_INTER_MODES
     case NEW_NEARESTMV: {
       nmv_context *const nmvc = &ec_ctx->nmvc;
       read_mv(r, &mv[0].as_mv, &ref_mv[0].as_mv, nmvc, allow_hp);
@@ -1625,6 +1672,7 @@
       assert(is_compound);
       break;
     }
+#endif  // !CONFIG_NEW_INTER_MODES
     case NEAR_NEWMV: {
       nmv_context *const nmvc = &ec_ctx->nmvc;
       mv[0].as_int = near_mv[0].as_int;
@@ -1749,7 +1797,12 @@
 
   if (mbmi->skip_mode) {
     assert(is_compound);
+#if CONFIG_NEW_INTER_MODES
+    mbmi->mode = NEAR_NEARMV;
+    mbmi->ref_mv_idx = 0;
+#else
     mbmi->mode = NEAREST_NEARESTMV;
+#endif  // !CONFIG_NEW_INTER_MODES
   } else {
     if (segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP) ||
         segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_GLOBALMV)) {
@@ -1779,7 +1832,11 @@
   }
 
   if (is_compound && mbmi->mode != GLOBAL_GLOBALMV) {
-    const int ref_mv_idx = mbmi->ref_mv_idx + 1;
+#if CONFIG_NEW_INTER_MODES
+    int ref_mv_idx = mbmi->ref_mv_idx;
+#else
+    int ref_mv_idx = mbmi->ref_mv_idx + 1;
+#endif  // CONFIG_NEW_INTER_MODES
     nearestmv[0] = xd->ref_mv_stack[ref_frame][0].this_mv;
     nearestmv[1] = xd->ref_mv_stack[ref_frame][0].comp_mv;
     nearmv[0] = xd->ref_mv_stack[ref_frame][ref_mv_idx].this_mv;
@@ -1792,21 +1849,28 @@
                        features->cur_frame_force_integer_mv);
     lower_mv_precision(&nearmv[1].as_mv, allow_hp,
                        features->cur_frame_force_integer_mv);
+#if CONFIG_NEW_INTER_MODES
+  } else if (mbmi->mode == NEARMV) {
+    nearmv[0] = xd->ref_mv_stack[mbmi->ref_frame[0]][mbmi->ref_mv_idx].this_mv;
+  }
+#else
   } else if (mbmi->ref_mv_idx > 0 && mbmi->mode == NEARMV) {
     nearmv[0] =
         xd->ref_mv_stack[mbmi->ref_frame[0]][1 + mbmi->ref_mv_idx].this_mv;
   }
+#endif  // CONFIG_NEW_INTER_MODES
 
   int_mv ref_mv[2] = { nearestmv[0], nearestmv[1] };
 
   if (is_compound) {
     int ref_mv_idx = mbmi->ref_mv_idx;
+#if !CONFIG_NEW_INTER_MODES
     // Special case: NEAR_NEWMV and NEW_NEARMV modes use
     // 1 + mbmi->ref_mv_idx (like NEARMV) instead of
     // mbmi->ref_mv_idx (like NEWMV)
     if (mbmi->mode == NEAR_NEWMV || mbmi->mode == NEW_NEARMV)
       ref_mv_idx = 1 + mbmi->ref_mv_idx;
-
+#endif  // !CONFIG_NEW_INTER_MODES
     // TODO(jingning, yunqing): Do we need a lower_mv_precision() call here?
     if (compound_ref0_mode(mbmi->mode) == NEWMV)
       ref_mv[0] = xd->ref_mv_stack[ref_frame][ref_mv_idx].this_mv;
@@ -1819,8 +1883,14 @@
         ref_mv[0] = xd->ref_mv_stack[ref_frame][mbmi->ref_mv_idx].this_mv;
     }
   }
-
+#if CONFIG_NEW_INTER_MODES
+  if (mbmi->skip_mode) {
+    assert(mbmi->mode == NEAR_NEARMV);
+    assert(mbmi->ref_mv_idx == 0);
+  }
+#else
   if (mbmi->skip_mode) assert(mbmi->mode == NEAREST_NEARESTMV);
+#endif  // CONFIG_NEW_INTER_MODES
 
   const int mv_corrupted_flag =
       !assign_mv(cm, xd, mbmi->mode, mbmi->ref_frame, mbmi->mv, ref_mv,
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index deca108..6513e9f 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -92,22 +92,44 @@
         (mode_ctx >> GLOBALMV_OFFSET) & GLOBALMV_CTX_MASK;
     aom_write_symbol(w, mode != GLOBALMV, ec_ctx->zeromv_cdf[zeromv_ctx], 2);
 
+#if !CONFIG_NEW_INTER_MODES
     if (mode != GLOBALMV) {
       int16_t refmv_ctx = (mode_ctx >> REFMV_OFFSET) & REFMV_CTX_MASK;
       aom_write_symbol(w, mode != NEARESTMV, ec_ctx->refmv_cdf[refmv_ctx], 2);
     }
+#endif  // !CONFIG_NEW_INTER_MODES
   }
 }
 
+#if CONFIG_NEW_INTER_MODES
+static void write_drl_idx(FRAME_CONTEXT *ec_ctx, const MB_MODE_INFO *mbmi,
+                          const MB_MODE_INFO_EXT_FRAME *mbmi_ext_frame,
+                          aom_writer *w) {
+  assert(!mbmi->skip_mode);
+  // Write the DRL index as a sequence of bits encoding a decision tree:
+  // 0 -> 0   10 -> 1   110 -> 2    111 -> 3
+  // Also use the number of reference MVs for a frame type to reduce the
+  // number of bits written if there are less than 4 valid DRL indices.
+  assert(mbmi->ref_mv_idx < mbmi_ext_frame->ref_mv_count);
+  assert(mbmi->ref_mv_idx < MAX_DRL_BITS + 1);
+  int range = AOMMIN(mbmi_ext_frame->ref_mv_count - 1, MAX_DRL_BITS);
+  for (int idx = 0; idx < range; ++idx) {
+    aom_cdf_prob *drl_cdf =
+        av1_get_drl_cdf(ec_ctx, mbmi_ext_frame->weight, idx);
+    aom_write_symbol(w, mbmi->ref_mv_idx != idx, drl_cdf, 2);
+    if (mbmi->ref_mv_idx == idx) break;
+  }
+}
+#else
 static AOM_INLINE void write_drl_idx(
     FRAME_CONTEXT *ec_ctx, const MB_MODE_INFO *mbmi,
     const MB_MODE_INFO_EXT_FRAME *mbmi_ext_frame, aom_writer *w) {
-  assert(mbmi->ref_mv_idx < 3);
+  assert(mbmi->ref_mv_idx < MAX_DRL_BITS + 1);
 
   const int new_mv = mbmi->mode == NEWMV || mbmi->mode == NEW_NEWMV;
   if (new_mv) {
     int idx;
-    for (idx = 0; idx < 2; ++idx) {
+    for (idx = 0; idx < MAX_DRL_BITS; ++idx) {
       if (mbmi_ext_frame->ref_mv_count > idx + 1) {
         uint8_t drl_ctx = av1_drl_ctx(mbmi_ext_frame->weight, idx);
 
@@ -122,7 +144,7 @@
   if (have_nearmv_in_inter_mode(mbmi->mode)) {
     int idx;
     // TODO(jingning): Temporary solution to compensate the NEARESTMV offset.
-    for (idx = 1; idx < 3; ++idx) {
+    for (idx = 1; idx < MAX_DRL_BITS + 1; ++idx) {
       if (mbmi_ext_frame->ref_mv_count > idx + 1) {
         uint8_t drl_ctx = av1_drl_ctx(mbmi_ext_frame->weight, idx);
         aom_write_symbol(w, mbmi->ref_mv_idx != (idx - 1),
@@ -133,6 +155,7 @@
     return;
   }
 }
+#endif  // CONFIG_NEW_INTER_MODES
 
 static AOM_INLINE void write_inter_compound_mode(MACROBLOCKD *xd, aom_writer *w,
                                                  PREDICTION_MODE mode,
@@ -1378,7 +1401,9 @@
   int ref_mv_idx = mbmi->ref_mv_idx;
   if (mbmi->mode == NEAR_NEWMV || mbmi->mode == NEW_NEARMV) {
     assert(has_second_ref(mbmi));
+#if !CONFIG_NEW_INTER_MODES
     ref_mv_idx += 1;
+#endif  // !CONFIG_NEW_INTER_MODES
   }
   return get_ref_mv_from_stack(ref_idx, mbmi->ref_frame, ref_mv_idx,
                                x->mbmi_ext_frame);
@@ -1463,6 +1488,17 @@
         av1_encode_mv(cpi, w, &mbmi->mv[ref].as_mv, &ref_mv.as_mv, nmvc,
                       allow_hp);
       }
+#if CONFIG_NEW_INTER_MODES
+    } else if (mode == NEAR_NEWMV) {
+      nmv_context *nmvc = &ec_ctx->nmvc;
+      const int_mv ref_mv = get_ref_mv(x, 1);
+      av1_encode_mv(cpi, w, &mbmi->mv[1].as_mv, &ref_mv.as_mv, nmvc, allow_hp);
+    } else if (mode == NEW_NEARMV) {
+      nmv_context *nmvc = &ec_ctx->nmvc;
+      const int_mv ref_mv = get_ref_mv(x, 0);
+      av1_encode_mv(cpi, w, &mbmi->mv[0].as_mv, &ref_mv.as_mv, nmvc, allow_hp);
+    }
+#else
     } else if (mode == NEAREST_NEWMV || mode == NEAR_NEWMV) {
       nmv_context *nmvc = &ec_ctx->nmvc;
       const int_mv ref_mv = get_ref_mv(x, 1);
@@ -1472,6 +1508,7 @@
       const int_mv ref_mv = get_ref_mv(x, 0);
       av1_encode_mv(cpi, w, &mbmi->mv[0].as_mv, &ref_mv.as_mv, nmvc, allow_hp);
     }
+#endif  // CONFIG_NEW_INTER_MODES
 
     if (cpi->common.current_frame.reference_mode != COMPOUND_REFERENCE &&
         cpi->common.seq_params.enable_interintra_compound &&
diff --git a/av1/encoder/block.h b/av1/encoder/block.h
index 4925157..bce5047 100644
--- a/av1/encoder/block.h
+++ b/av1/encoder/block.h
@@ -685,10 +685,15 @@
   int newmv_mode_cost[NEWMV_MODE_CONTEXTS][2];
   //! zeromv_mode_cost
   int zeromv_mode_cost[GLOBALMV_MODE_CONTEXTS][2];
+#if CONFIG_NEW_INTER_MODES
+  //! drl_mode_cost
+  int drl_mode_cost[3][DRL_MODE_CONTEXTS][2];
+#else
   //! refmv_mode_cost
   int refmv_mode_cost[REFMV_MODE_CONTEXTS][2];
   //! drl_mode_cost0
   int drl_mode_cost0[DRL_MODE_CONTEXTS][2];
+#endif  // CONFIG_NEW_INTER_MODES
   /**@}*/
 
   /*****************************************************************************
diff --git a/av1/encoder/enc_enums.h b/av1/encoder/enc_enums.h
index ff191ff..3777d66 100644
--- a/av1/encoder/enc_enums.h
+++ b/av1/encoder/enc_enums.h
@@ -18,6 +18,152 @@
 
 // This enumerator type needs to be kept aligned with the mode order in
 // const MODE_DEFINITION av1_mode_defs[MAX_MODES] used in the rd code.
+#if CONFIG_NEW_INTER_MODES
+enum {
+  THR_NEARMV,
+  THR_NEARL2,
+  THR_NEARL3,
+  THR_NEARB,
+  THR_NEARA2,
+  THR_NEARA,
+  THR_NEARG,
+
+  THR_NEWMV,
+  THR_NEWL2,
+  THR_NEWL3,
+  THR_NEWB,
+  THR_NEWA2,
+  THR_NEWA,
+  THR_NEWG,
+
+  THR_GLOBALMV,
+  THR_GLOBALL2,
+  THR_GLOBALL3,
+  THR_GLOBALB,
+  THR_GLOBALA2,
+  THR_GLOBALG,
+  THR_GLOBALA,
+
+  THR_COMP_NEAR_NEARLA,
+  THR_COMP_NEAR_NEARL2A,
+  THR_COMP_NEAR_NEARL3A,
+  THR_COMP_NEAR_NEARGA,
+  THR_COMP_NEAR_NEARLB,
+  THR_COMP_NEAR_NEARL2B,
+  THR_COMP_NEAR_NEARL3B,
+  THR_COMP_NEAR_NEARGB,
+  THR_COMP_NEAR_NEARLA2,
+  THR_COMP_NEAR_NEARL2A2,
+  THR_COMP_NEAR_NEARL3A2,
+  THR_COMP_NEAR_NEARGA2,
+  THR_COMP_NEAR_NEARLL2,
+  THR_COMP_NEAR_NEARLL3,
+  THR_COMP_NEAR_NEARLG,
+  THR_COMP_NEAR_NEARBA,
+
+  THR_COMP_NEW_NEARLA,
+  THR_COMP_NEAR_NEWLA,
+  THR_COMP_NEW_NEWLA,
+  THR_COMP_GLOBAL_GLOBALLA,
+
+  THR_COMP_NEW_NEARL2A,
+  THR_COMP_NEAR_NEWL2A,
+  THR_COMP_NEW_NEWL2A,
+  THR_COMP_GLOBAL_GLOBALL2A,
+
+  THR_COMP_NEW_NEARL3A,
+  THR_COMP_NEAR_NEWL3A,
+  THR_COMP_NEW_NEWL3A,
+  THR_COMP_GLOBAL_GLOBALL3A,
+
+  THR_COMP_NEW_NEARGA,
+  THR_COMP_NEAR_NEWGA,
+  THR_COMP_NEW_NEWGA,
+  THR_COMP_GLOBAL_GLOBALGA,
+
+  THR_COMP_NEW_NEARLB,
+  THR_COMP_NEAR_NEWLB,
+  THR_COMP_NEW_NEWLB,
+  THR_COMP_GLOBAL_GLOBALLB,
+
+  THR_COMP_NEW_NEARL2B,
+  THR_COMP_NEAR_NEWL2B,
+  THR_COMP_NEW_NEWL2B,
+  THR_COMP_GLOBAL_GLOBALL2B,
+
+  THR_COMP_NEW_NEARL3B,
+  THR_COMP_NEAR_NEWL3B,
+  THR_COMP_NEW_NEWL3B,
+  THR_COMP_GLOBAL_GLOBALL3B,
+
+  THR_COMP_NEW_NEARGB,
+  THR_COMP_NEAR_NEWGB,
+  THR_COMP_NEW_NEWGB,
+  THR_COMP_GLOBAL_GLOBALGB,
+
+  THR_COMP_NEW_NEARLA2,
+  THR_COMP_NEAR_NEWLA2,
+  THR_COMP_NEW_NEWLA2,
+  THR_COMP_GLOBAL_GLOBALLA2,
+
+  THR_COMP_NEW_NEARL2A2,
+  THR_COMP_NEAR_NEWL2A2,
+  THR_COMP_NEW_NEWL2A2,
+  THR_COMP_GLOBAL_GLOBALL2A2,
+
+  THR_COMP_NEW_NEARL3A2,
+  THR_COMP_NEAR_NEWL3A2,
+  THR_COMP_NEW_NEWL3A2,
+  THR_COMP_GLOBAL_GLOBALL3A2,
+
+  THR_COMP_NEW_NEARGA2,
+  THR_COMP_NEAR_NEWGA2,
+  THR_COMP_NEW_NEWGA2,
+  THR_COMP_GLOBAL_GLOBALGA2,
+
+  THR_COMP_NEW_NEARLL2,
+  THR_COMP_NEAR_NEWLL2,
+  THR_COMP_NEW_NEWLL2,
+  THR_COMP_GLOBAL_GLOBALLL2,
+
+  THR_COMP_NEW_NEARLL3,
+  THR_COMP_NEAR_NEWLL3,
+  THR_COMP_NEW_NEWLL3,
+  THR_COMP_GLOBAL_GLOBALLL3,
+
+  THR_COMP_NEW_NEARLG,
+  THR_COMP_NEAR_NEWLG,
+  THR_COMP_NEW_NEWLG,
+  THR_COMP_GLOBAL_GLOBALLG,
+
+  THR_COMP_NEW_NEARBA,
+  THR_COMP_NEAR_NEWBA,
+  THR_COMP_NEW_NEWBA,
+  THR_COMP_GLOBAL_GLOBALBA,
+
+  THR_DC,
+  THR_PAETH,
+  THR_SMOOTH,
+  THR_SMOOTH_V,
+  THR_SMOOTH_H,
+  THR_H_PRED,
+  THR_V_PRED,
+  THR_D135_PRED,
+  THR_D203_PRED,
+  THR_D157_PRED,
+  THR_D67_PRED,
+  THR_D113_PRED,
+  THR_D45_PRED,
+
+  MAX_MODES,
+  SINGLE_REF_MODE_START = THR_NEARMV,
+  SINGLE_REF_MODE_END = THR_COMP_NEAR_NEARLA,
+  NUM_SINGLE_REF_MODES = SINGLE_REF_MODE_END - SINGLE_REF_MODE_START,
+  THR_MODE_START = THR_NEARMV,
+  THR_MODE_END = MAX_MODES,
+  THR_INVALID = 255
+} UENUM1BYTE(THR_MODES);
+#else
 enum {
   THR_NEARESTMV,
   THR_NEARESTL2,
@@ -218,6 +364,7 @@
   THR_MODE_END = MAX_MODES,
   THR_INVALID = 255
 } UENUM1BYTE(THR_MODES);
+#endif  // CONFIG_NEW_INTER_MODES
 
 enum {
   THR_LAST,
diff --git a/av1/encoder/encodeframe_utils.c b/av1/encoder/encodeframe_utils.c
index 4c96b59..e9dcfe9 100644
--- a/av1/encoder/encodeframe_utils.c
+++ b/av1/encoder/encodeframe_utils.c
@@ -448,12 +448,13 @@
   ++counts->zeromv_mode[mode_ctx][1];
 #endif
   update_cdf(fc->zeromv_cdf[mode_ctx], 1, 2);
-
+#if !CONFIG_NEW_INTER_MODES
   mode_ctx = (mode_context >> REFMV_OFFSET) & REFMV_CTX_MASK;
 #if CONFIG_ENTROPY_STATS
   ++counts->refmv_mode[mode_ctx][mode != NEARESTMV];
-#endif
+#endif  // CONFIG_ENTROPY_STATS
   update_cdf(fc->refmv_cdf[mode_ctx], mode != NEARESTMV, 2);
+#endif  // !CONFIG_NEW_INTER_MODES
 }
 
 static void update_palette_cdf(MACROBLOCKD *xd, const MB_MODE_INFO *const mbmi,
@@ -1225,8 +1226,14 @@
   AVERAGE_CDF(ctx_left->coeff_br_cdf, ctx_tr->coeff_br_cdf, BR_CDF_SIZE);
   AVERAGE_CDF(ctx_left->newmv_cdf, ctx_tr->newmv_cdf, 2);
   AVERAGE_CDF(ctx_left->zeromv_cdf, ctx_tr->zeromv_cdf, 2);
+#if CONFIG_NEW_INTER_MODES
+  AVERAGE_CDF(ctx_left->drl_cdf[0], ctx_tr->drl_cdf[0], 2);
+  AVERAGE_CDF(ctx_left->drl_cdf[1], ctx_tr->drl_cdf[1], 2);
+  AVERAGE_CDF(ctx_left->drl_cdf[2], ctx_tr->drl_cdf[2], 2);
+#else
   AVERAGE_CDF(ctx_left->refmv_cdf, ctx_tr->refmv_cdf, 2);
   AVERAGE_CDF(ctx_left->drl_cdf, ctx_tr->drl_cdf, 2);
+#endif  // CONFIG_NEW_INTER_MODES
   AVERAGE_CDF(ctx_left->inter_compound_mode_cdf,
               ctx_tr->inter_compound_mode_cdf, INTER_COMPOUND_MODES);
   AVERAGE_CDF(ctx_left->compound_type_cdf, ctx_tr->compound_type_cdf,
diff --git a/av1/encoder/encodemv.c b/av1/encoder/encodemv.c
index 167e9c0..28fb688 100644
--- a/av1/encoder/encodemv.c
+++ b/av1/encoder/encodemv.c
@@ -250,12 +250,46 @@
   int ref_mv_idx = mbmi->ref_mv_idx;
   if (mbmi->mode == NEAR_NEWMV || mbmi->mode == NEW_NEARMV) {
     assert(has_second_ref(mbmi));
+#if !CONFIG_NEW_INTER_MODES
     ref_mv_idx += 1;
+#endif  // !CONFIG_NEW_INTER_MODES
   }
   return av1_get_ref_mv_from_stack(ref_idx, mbmi->ref_frame, ref_mv_idx,
                                    x->mbmi_ext);
 }
 
+#if CONFIG_NEW_INTER_MODES
+/**
+ * Get the best reference MV (for use with intrabc) from the refmv stack.
+ * This function will search all available references and return the first one
+ * that is not zero or invalid.
+ *
+ * @param allow_hp Can high-precision be used?
+ * @param mbmi_ext The MB ext struct.  Used in get_ref_mv_from_stack.
+ * @param ref_frame The reference frame to find motion vectors from.
+ * @param is_integer is the MV an integer?
+ * @return The best MV, or INVALID_MV if none exists.
+ */
+int_mv av1_find_best_ref_mv_from_stack(int allow_hp,
+                                       const MB_MODE_INFO_EXT *mbmi_ext,
+                                       MV_REFERENCE_FRAME ref_frame,
+                                       int is_integer) {
+  int_mv mv;
+  bool found_ref_mv = false;
+  MV_REFERENCE_FRAME ref_frames[2] = { ref_frame, NONE_FRAME };
+  int range = AOMMIN(mbmi_ext->ref_mv_count[ref_frame], MAX_REF_MV_STACK_SIZE);
+  for (int i = 0; i < range; i++) {
+    mv = av1_get_ref_mv_from_stack(0, ref_frames, i, mbmi_ext);
+    if (mv.as_int != 0 && mv.as_int != INVALID_MV) {
+      found_ref_mv = true;
+      break;
+    }
+  }
+  lower_mv_precision(&mv.as_mv, allow_hp, is_integer);
+  if (!found_ref_mv) mv.as_int = INVALID_MV;
+  return mv;
+}
+#else
 void av1_find_best_ref_mvs_from_stack(int allow_hp,
                                       const MB_MODE_INFO_EXT *mbmi_ext,
                                       MV_REFERENCE_FRAME ref_frame,
@@ -268,3 +302,4 @@
   *near_mv = av1_get_ref_mv_from_stack(ref_idx, ref_frames, 1, mbmi_ext);
   lower_mv_precision(&near_mv->as_mv, allow_hp, is_integer);
 }
+#endif  // CONFIG_NEW_INTER_MODES
diff --git a/av1/encoder/encodemv.h b/av1/encoder/encodemv.h
index 9f0d607..6a7d1a6 100644
--- a/av1/encoder/encodemv.h
+++ b/av1/encoder/encodemv.h
@@ -37,11 +37,17 @@
                                  const MV_REFERENCE_FRAME *ref_frame,
                                  int ref_mv_idx,
                                  const MB_MODE_INFO_EXT *mbmi_ext);
+#if CONFIG_NEW_INTER_MODES
+int_mv av1_find_best_ref_mv_from_stack(int allow_hp,
+#else
 void av1_find_best_ref_mvs_from_stack(int allow_hp,
-                                      const MB_MODE_INFO_EXT *mbmi_ext,
-                                      MV_REFERENCE_FRAME ref_frame,
-                                      int_mv *nearest_mv, int_mv *near_mv,
-                                      int is_integer);
+#endif  // CONFIG_NEW_INTER_MODES
+                                       const MB_MODE_INFO_EXT *mbmi_ext,
+                                       MV_REFERENCE_FRAME ref_frame,
+#if !CONFIG_NEW_INTER_MODES
+                                       int_mv *nearest_mv, int_mv *near_mv,
+#endif  // CONFIG_NEW_INTER_MODES
+                                       int is_integer);
 
 static INLINE MV_JOINT_TYPE av1_get_mv_joint(const MV *mv) {
   // row:  Z  col:  Z  | MV_JOINT_ZERO   (0)
@@ -82,12 +88,20 @@
         mbmi->mv[1].as_int == ref_mv_1.as_int) {
       return 0;
     }
+#if CONFIG_NEW_INTER_MODES
+  } else if (this_mode == NEAR_NEWMV) {
+#else
   } else if (this_mode == NEAREST_NEWMV || this_mode == NEAR_NEWMV) {
+#endif  // CONFIG_NEW_INTER_MODES
     const int_mv ref_mv_1 = av1_get_ref_mv(x, 1);
     if (mbmi->mv[1].as_int == ref_mv_1.as_int) {
       return 0;
     }
+#if CONFIG_NEW_INTER_MODES
+  } else if (this_mode == NEW_NEARMV) {
+#else
   } else if (this_mode == NEW_NEARESTMV || this_mode == NEW_NEARMV) {
+#endif  // CONFIG_NEW_INTER_MODES
     const int_mv ref_mv_0 = av1_get_ref_mv(x, 0);
     if (mbmi->mv[0].as_int == ref_mv_0.as_int) {
       return 0;
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index a8db912..9da84bb 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -1154,8 +1154,12 @@
                                    [SIG_COEF_CONTEXTS_EOB][NUM_BASE_LEVELS + 1];
   unsigned int newmv_mode[NEWMV_MODE_CONTEXTS][2];
   unsigned int zeromv_mode[GLOBALMV_MODE_CONTEXTS][2];
+#if CONFIG_NEW_INTER_MODES
+  unsigned int drl_mode[3][DRL_MODE_CONTEXTS][2];
+#else
   unsigned int refmv_mode[REFMV_MODE_CONTEXTS][2];
   unsigned int drl_mode[DRL_MODE_CONTEXTS][2];
+#endif  // CONFIG_NEW_INTER_MODES
   unsigned int inter_compound_mode[INTER_COMPOUND_MODE_CONTEXTS]
                                   [INTER_COMPOUND_MODES];
   unsigned int wedge_idx[BLOCK_SIZES_ALL][16];
diff --git a/av1/encoder/motion_search_facade.c b/av1/encoder/motion_search_facade.c
index e76575c..ca271ad 100644
--- a/av1/encoder/motion_search_facade.c
+++ b/av1/encoder/motion_search_facade.c
@@ -697,12 +697,17 @@
   mbmi->interinter_comp.seg_mask = xd->seg_mask;
   const INTERINTER_COMPOUND_DATA *compound_data = &mbmi->interinter_comp;
 
+#if CONFIG_NEW_INTER_MODES
+  const int mixed_new = this_mode == NEAR_NEWMV || this_mode == NEW_NEARMV;
+#else
+  const int mixed_new = this_mode >= NEAREST_NEWMV && this_mode <= NEW_NEARMV;
+#endif  // CONFIG_NEW_INTER_MODES
   if (this_mode == NEW_NEWMV) {
     do_masked_motion_search_indexed(cpi, x, cur_mv, compound_data, bsize,
                                     tmp_mv, &tmp_rate_mv, 2);
     mbmi->mv[0].as_int = tmp_mv[0].as_int;
     mbmi->mv[1].as_int = tmp_mv[1].as_int;
-  } else if (this_mode >= NEAREST_NEWMV && this_mode <= NEW_NEARMV) {
+  } else if (mixed_new) {
     // which = 1 if this_mode == NEAREST_NEWMV || this_mode == NEAR_NEWMV
     // which = 0 if this_mode == NEW_NEARESTMV || this_mode == NEW_NEARMV
     int which = (NEWMV == compound_ref1_mode(this_mode));
diff --git a/av1/encoder/mv_prec.c b/av1/encoder/mv_prec.c
index f5250f5..e7a4b92 100644
--- a/av1/encoder/mv_prec.c
+++ b/av1/encoder/mv_prec.c
@@ -26,7 +26,9 @@
   int ref_mv_idx = mbmi->ref_mv_idx;
   if (mbmi->mode == NEAR_NEWMV || mbmi->mode == NEW_NEARMV) {
     assert(has_second_ref(mbmi));
+#if !CONFIG_NEW_INTER_MODES
     ref_mv_idx += 1;
+#endif  // !CONFIG_NEW_INTER_MODES
   }
 
   const MV_REFERENCE_FRAME *ref_frames = mbmi->ref_frame;
@@ -210,12 +212,19 @@
       const MV cur_mv = mbmi->mv[ref_idx].as_mv;
       keep_one_mv_stat(mv_stats, &ref_mv, &cur_mv, cpi);
     }
+#if CONFIG_NEW_INTER_MODES
+  } else if (mode == NEAR_NEWMV || mode == NEW_NEARMV) {
+#else
   } else if (mode == NEAREST_NEWMV || mode == NEAR_NEWMV ||
              mode == NEW_NEARESTMV || mode == NEW_NEARMV) {
+#endif  // CONFIG_NEW_INTER_MODES
     // has exactly one new_mv
     mv_stats->default_mvs += 1;
-
+#if CONFIG_NEW_INTER_MODES
+    const int ref_idx = (mode == NEAR_NEWMV);
+#else
     const int ref_idx = (mode == NEAREST_NEWMV || mode == NEAR_NEWMV);
+#endif  // CONFIG_NEW_INTER_MODES
     const MV ref_mv =
         get_ref_mv_for_mv_stats(mbmi, mbmi_ext_frame, ref_idx).as_mv;
     const MV cur_mv = mbmi->mv[ref_idx].as_mv;
diff --git a/av1/encoder/nonrd_pickmode.c b/av1/encoder/nonrd_pickmode.c
index 23c5df8..e76479a 100644
--- a/av1/encoder/nonrd_pickmode.c
+++ b/av1/encoder/nonrd_pickmode.c
@@ -67,6 +67,20 @@
   { 9, 10, 13, 14 }, { 11, 12, 15, 16 }, { 17, 18, 21, 22 }, { 19, 20, 23, 24 }
 };
 
+#if CONFIG_NEW_INTER_MODES
+#define RT_INTER_MODES 6
+static const REF_MODE ref_mode_set[RT_INTER_MODES] = {
+  { LAST_FRAME, NEARMV },  { LAST_FRAME, NEWMV },    { GOLDEN_FRAME, NEARMV },
+  { GOLDEN_FRAME, NEWMV }, { ALTREF_FRAME, NEARMV }, { ALTREF_FRAME, NEWMV }
+};
+
+static const THR_MODES mode_idx[REF_FRAMES][4] = {
+  { THR_DC, THR_V_PRED, THR_H_PRED, THR_SMOOTH },
+  { THR_NEARMV, THR_NEARMV, THR_GLOBALMV, THR_NEWMV },
+  { THR_NEARG, THR_NEARG, THR_GLOBALMV, THR_NEWG },
+  { THR_NEARA, THR_NEARA, THR_GLOBALMV, THR_NEWA },
+};
+#else
 #define RT_INTER_MODES 9
 static const REF_MODE ref_mode_set[RT_INTER_MODES] = {
   { LAST_FRAME, NEARESTMV },   { LAST_FRAME, NEARMV },
@@ -83,12 +97,17 @@
   { THR_NEARESTL3, THR_NEARL3, THR_GLOBALL3, THR_NEWL3 },
   { THR_NEARESTG, THR_NEARG, THR_GLOBALMV, THR_NEWG },
 };
+#endif  // CONFIG_NEW_INTER_MODES
 
 static const PREDICTION_MODE intra_mode_list[] = { DC_PRED, V_PRED, H_PRED,
                                                    SMOOTH_PRED };
 
 static INLINE int mode_offset(const PREDICTION_MODE mode) {
+#if CONFIG_NEW_INTER_MODES
+  if (mode >= NEARMV) {
+#else
   if (mode >= NEARESTMV) {
+#endif  // CONFIG_NEW_INTER_MODES
     return INTER_OFFSET(mode);
   } else {
     switch (mode) {
@@ -101,6 +120,13 @@
   }
 }
 
+#if CONFIG_NEW_INTER_MODES
+enum {
+  INTER_NEW = (1 << NEWMV),
+  INTER_NEAR = (1 << NEARMV),
+  INTER_NEAR_NEW = (1 << NEARMV) | (1 << NEWMV),
+};
+#else
 enum {
   //  INTER_ALL = (1 << NEARESTMV) | (1 << NEARMV) | (1 << NEWMV),
   INTER_NEAREST = (1 << NEARESTMV),
@@ -108,9 +134,14 @@
   INTER_NEAREST_NEAR = (1 << NEARESTMV) | (1 << NEARMV),
   INTER_NEAR_NEW = (1 << NEARMV) | (1 << NEWMV),
 };
+#endif  // CONFIG_NEW_INTER_MODES
 
 static INLINE void init_best_pickmode(BEST_PICKMODE *bp) {
+#if CONFIG_NEW_INTER_MODES
+  bp->best_mode = NEARMV;
+#else
   bp->best_mode = NEARESTMV;
+#endif  // CONFIG_NEW_INTER_MODES
   bp->best_ref_frame = LAST_FRAME;
   bp->best_tx_size = TX_8X8;
 #if CONFIG_REMOVE_DUAL_FILTER
@@ -360,9 +391,17 @@
     // TODO(Ravi): Populate mbmi_ext->ref_mv_stack[ref_frame][4] and
     // mbmi_ext->weight[ref_frame][4] inside av1_find_mv_refs.
     av1_copy_usable_ref_mv_stack_and_weight(xd, mbmi_ext, ref_frame);
+#if CONFIG_NEW_INTER_MODES
+    frame_mv[NEARMV][ref_frame] =
+        av1_find_best_ref_mv_from_stack(cm->features.allow_high_precision_mv,
+                                        mbmi_ext, ref_frame, /*is_integer=*/0);
+#else
     av1_find_best_ref_mvs_from_stack(
         cm->features.allow_high_precision_mv, mbmi_ext, ref_frame,
-        &frame_mv[NEARESTMV][ref_frame], &frame_mv[NEARMV][ref_frame], 0);
+        &frame_mv[NEARESTMV][ref_frame], &frame_mv[NEARMV][ref_frame],
+        /*is_integer=*/0);
+#endif  // CONFIG_NEW_INTER_MODES
+
     // Early exit for non-LAST frame if force_skip_low_temp_var is set.
     if (!av1_is_scaled(sf) && bsize >= BLOCK_8X8 &&
         !(force_skip_low_temp_var && ref_frame != LAST_FRAME)) {
@@ -1072,7 +1111,9 @@
     } else {
       mode_cost += mode_costs->zeromv_mode_cost[mode_ctx][1];
       mode_ctx = (mode_context >> REFMV_OFFSET) & REFMV_CTX_MASK;
+#if !CONFIG_NEW_INTER_MODES
       mode_cost += mode_costs->refmv_mode_cost[mode_ctx][mode != NEARESTMV];
+#endif  // !CONFIG_NEW_INTER_MODES
       return mode_cost;
     }
   }
@@ -2219,7 +2260,11 @@
         continue;
     }
 
+#if CONFIG_NEW_INTER_MODES
+    for (PREDICTION_MODE inter_mv_mode = NEARMV; inter_mv_mode <= NEWMV;
+#else
     for (PREDICTION_MODE inter_mv_mode = NEARESTMV; inter_mv_mode <= NEWMV;
+#endif  // CONFIG_NEW_INTER_MODES
          inter_mv_mode++) {
       if (inter_mv_mode == this_mode) continue;
       if (mode_checked[inter_mv_mode][ref_frame] &&
@@ -2443,7 +2488,11 @@
       }
     } else {
       PREDICTION_MODE this_mode;
+#if CONFIG_NEW_INTER_MODES
+      for (this_mode = NEARMV; this_mode <= NEWMV; ++this_mode) {
+#else
       for (this_mode = NEARESTMV; this_mode <= NEWMV; ++this_mode) {
+#endif  // CONFIG_NEW_INTER_MODES
         update_thresh_freq_fact(cpi, x, bsize, best_pickmode.best_ref_frame,
                                 best_mode_idx, this_mode);
       }
diff --git a/av1/encoder/partition_search.c b/av1/encoder/partition_search.c
index 3f02e1d..50ad101 100644
--- a/av1/encoder/partition_search.c
+++ b/av1/encoder/partition_search.c
@@ -873,6 +873,35 @@
 #endif
 }
 
+#if CONFIG_NEW_INTER_MODES
+static void update_drl_index_stats(FRAME_CONTEXT *fc, FRAME_COUNTS *counts,
+                                   const MB_MODE_INFO *mbmi,
+                                   const MB_MODE_INFO_EXT *mbmi_ext) {
+#if !CONFIG_ENTROPY_STATS
+  (void)counts;
+#endif  // !CONFIG_ENTROPY_STATS
+  assert(have_drl_index(mbmi->mode));
+  uint8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
+  assert(mbmi->ref_mv_idx < MAX_DRL_BITS + 1);
+  const int range =
+      AOMMIN(mbmi_ext->ref_mv_count[ref_frame_type] - 1, MAX_DRL_BITS);
+  for (int idx = 0; idx < range; ++idx) {
+    aom_cdf_prob *drl_cdf =
+        av1_get_drl_cdf(fc, mbmi_ext->weight[ref_frame_type], idx);
+#if CONFIG_ENTROPY_STATS
+    int drl_ctx = av1_drl_ctx(mbmi_ext->weight[ref_frame_type], idx);
+    switch (mbmi->ref_mv_idx) {
+      case 0: counts->drl_mode[0][drl_ctx][mbmi->ref_mv_idx != idx]++; break;
+      case 1: counts->drl_mode[1][drl_ctx][mbmi->ref_mv_idx != idx]++; break;
+      default: counts->drl_mode[2][drl_ctx][mbmi->ref_mv_idx != idx]++; break;
+    }
+#endif  // CONFIG_ENTROPY_STATS
+    update_cdf(drl_cdf, mbmi->ref_mv_idx != idx, 2);
+    if (mbmi->ref_mv_idx == idx) break;
+  }
+}
+#endif  // CONFIG_NEW_INTER_MODES
+
 static void update_stats(const AV1_COMMON *const cm, ThreadData *td) {
   MACROBLOCK *x = &td->mb;
   MACROBLOCKD *const xd = &x->e_mbd;
@@ -1262,6 +1291,11 @@
     }
 
     const int new_mv = mbmi->mode == NEWMV || mbmi->mode == NEW_NEWMV;
+#if CONFIG_NEW_INTER_MODES
+    if (have_drl_index(mbmi->mode)) {
+      update_drl_index_stats(fc, counts, mbmi, mbmi_ext);
+    }
+#else
     if (new_mv) {
       const uint8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
       for (int idx = 0; idx < 2; ++idx) {
@@ -1276,7 +1310,6 @@
         }
       }
     }
-
     if (have_nearmv_in_inter_mode(mbmi->mode)) {
       const uint8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
       for (int idx = 1; idx < 3; ++idx) {
@@ -1291,6 +1324,7 @@
         }
       }
     }
+#endif  // CONFIG_NEW_INTER_MODES
 #if CONFIG_SDP
     if (have_newmv_in_inter_mode(mbmi->mode) && xd->tree_type != CHROMA_PART) {
 #else
@@ -1305,6 +1339,13 @@
           av1_update_mv_stats(&mbmi->mv[ref].as_mv, &ref_mv.as_mv, &fc->nmvc,
                               allow_hp);
         }
+#if CONFIG_NEW_INTER_MODES
+      } else if (mbmi->mode == NEAR_NEWMV || mbmi->mode == NEW_NEARMV) {
+        const int ref = mbmi->mode == NEAR_NEWMV;
+        const int_mv ref_mv = av1_get_ref_mv(x, ref);
+        av1_update_mv_stats(&mbmi->mv[ref].as_mv, &ref_mv.as_mv, &fc->nmvc,
+                            allow_hp);
+#else
       } else if (mbmi->mode == NEAREST_NEWMV || mbmi->mode == NEAR_NEWMV) {
         const int ref = 1;
         const int_mv ref_mv = av1_get_ref_mv(x, ref);
@@ -1315,6 +1356,7 @@
         const int_mv ref_mv = av1_get_ref_mv(x, ref);
         av1_update_mv_stats(&mbmi->mv[ref].as_mv, &ref_mv.as_mv, &fc->nmvc,
                             allow_hp);
+#endif  // CONFIG_NEW_INTER_MODES
       }
     }
   }
diff --git a/av1/encoder/rd.c b/av1/encoder/rd.c
index bf529af..e4cb424 100644
--- a/av1/encoder/rd.c
+++ b/av1/encoder/rd.c
@@ -324,6 +324,16 @@
                                fc->zeromv_cdf[i], NULL);
     }
 
+#if CONFIG_NEW_INTER_MODES
+    for (i = 0; i < DRL_MODE_CONTEXTS; ++i) {
+      av1_cost_tokens_from_cdf(mode_costs->drl_mode_cost[0][i],
+                               fc->drl_cdf[0][i], NULL);
+      av1_cost_tokens_from_cdf(mode_costs->drl_mode_cost[1][i],
+                               fc->drl_cdf[1][i], NULL);
+      av1_cost_tokens_from_cdf(mode_costs->drl_mode_cost[2][i],
+                               fc->drl_cdf[2][i], NULL);
+    }
+#else
     for (i = 0; i < REFMV_MODE_CONTEXTS; ++i) {
       av1_cost_tokens_from_cdf(mode_costs->refmv_mode_cost[i], fc->refmv_cdf[i],
                                NULL);
@@ -333,6 +343,7 @@
       av1_cost_tokens_from_cdf(mode_costs->drl_mode_cost0[i], fc->drl_cdf[i],
                                NULL);
     }
+#endif  // CONFIG_NEW_INTER_MODES
     for (i = 0; i < INTER_COMPOUND_MODE_CONTEXTS; ++i)
       av1_cost_tokens_from_cdf(mode_costs->inter_compound_mode_cost[i],
                                fc->inter_compound_mode_cdf[i], NULL);
@@ -1285,6 +1296,7 @@
   // Set baseline threshold values.
   av1_zero(rd->thresh_mult);
 
+#if !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_NEARESTMV] = 300;
   rd->thresh_mult[THR_NEARESTL2] = 300;
   rd->thresh_mult[THR_NEARESTL3] = 300;
@@ -1300,6 +1312,25 @@
   rd->thresh_mult[THR_NEWA2] = 1100;
   rd->thresh_mult[THR_NEWA] = 1000;
   rd->thresh_mult[THR_NEWG] = 1000;
+#endif  // !CONFIG_NEW_INTER_MODES
+
+#if CONFIG_NEW_INTER_MODES
+  rd->thresh_mult[THR_NEARMV] = 0;
+  rd->thresh_mult[THR_NEARL2] = 0;
+  rd->thresh_mult[THR_NEARL3] = 100;
+  rd->thresh_mult[THR_NEARB] = 0;
+  rd->thresh_mult[THR_NEARA2] = 0;
+  rd->thresh_mult[THR_NEARA] = 0;
+  rd->thresh_mult[THR_NEARG] = 0;
+#else
+  rd->thresh_mult[THR_NEARMV] = 1000;
+  rd->thresh_mult[THR_NEARL2] = 1000;
+  rd->thresh_mult[THR_NEARL3] = 1000;
+  rd->thresh_mult[THR_NEARB] = 1000;
+  rd->thresh_mult[THR_NEARA2] = 1000;
+  rd->thresh_mult[THR_NEARA] = 1000;
+  rd->thresh_mult[THR_NEARG] = 1000;
+#endif  // CONFIG_NEW_INTER_MODES
 
   rd->thresh_mult[THR_NEARMV] = 1000;
   rd->thresh_mult[THR_NEARL2] = 1000;
@@ -1317,6 +1348,7 @@
   rd->thresh_mult[THR_GLOBALG] = 2000;
   rd->thresh_mult[THR_GLOBALA] = 2400;
 
+#if !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAREST_NEARESTLA] = 1100;
   rd->thresh_mult[THR_COMP_NEAREST_NEARESTL2A] = 1000;
   rd->thresh_mult[THR_COMP_NEAREST_NEARESTL3A] = 800;
@@ -1334,130 +1366,164 @@
   rd->thresh_mult[THR_COMP_NEAREST_NEARESTLL3] = 2000;
   rd->thresh_mult[THR_COMP_NEAREST_NEARESTLG] = 2000;
   rd->thresh_mult[THR_COMP_NEAREST_NEARESTBA] = 2000;
+#endif  // !CONFIG_NEW_INTER_MODES
 
   rd->thresh_mult[THR_COMP_NEAR_NEARLA] = 1200;
+#if !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAREST_NEWLA] = 1500;
   rd->thresh_mult[THR_COMP_NEW_NEARESTLA] = 1500;
+#endif  // !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAR_NEWLA] = 1530;
   rd->thresh_mult[THR_COMP_NEW_NEARLA] = 1870;
   rd->thresh_mult[THR_COMP_NEW_NEWLA] = 2400;
   rd->thresh_mult[THR_COMP_GLOBAL_GLOBALLA] = 2750;
 
   rd->thresh_mult[THR_COMP_NEAR_NEARL2A] = 1200;
+#if !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAREST_NEWL2A] = 1500;
   rd->thresh_mult[THR_COMP_NEW_NEARESTL2A] = 1500;
+#endif  // !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAR_NEWL2A] = 1870;
   rd->thresh_mult[THR_COMP_NEW_NEARL2A] = 1700;
   rd->thresh_mult[THR_COMP_NEW_NEWL2A] = 1800;
   rd->thresh_mult[THR_COMP_GLOBAL_GLOBALL2A] = 2500;
 
   rd->thresh_mult[THR_COMP_NEAR_NEARL3A] = 1200;
+#if !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAREST_NEWL3A] = 1500;
   rd->thresh_mult[THR_COMP_NEW_NEARESTL3A] = 1500;
+#endif  // !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAR_NEWL3A] = 1700;
   rd->thresh_mult[THR_COMP_NEW_NEARL3A] = 1700;
   rd->thresh_mult[THR_COMP_NEW_NEWL3A] = 2000;
   rd->thresh_mult[THR_COMP_GLOBAL_GLOBALL3A] = 3000;
 
   rd->thresh_mult[THR_COMP_NEAR_NEARGA] = 1320;
+#if !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAREST_NEWGA] = 1500;
   rd->thresh_mult[THR_COMP_NEW_NEARESTGA] = 1500;
+#endif  // !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAR_NEWGA] = 2040;
   rd->thresh_mult[THR_COMP_NEW_NEARGA] = 1700;
   rd->thresh_mult[THR_COMP_NEW_NEWGA] = 2000;
   rd->thresh_mult[THR_COMP_GLOBAL_GLOBALGA] = 2250;
 
   rd->thresh_mult[THR_COMP_NEAR_NEARLB] = 1200;
+#if !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAREST_NEWLB] = 1500;
   rd->thresh_mult[THR_COMP_NEW_NEARESTLB] = 1500;
+#endif  // !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAR_NEWLB] = 1360;
   rd->thresh_mult[THR_COMP_NEW_NEARLB] = 1700;
   rd->thresh_mult[THR_COMP_NEW_NEWLB] = 2400;
   rd->thresh_mult[THR_COMP_GLOBAL_GLOBALLB] = 2250;
 
   rd->thresh_mult[THR_COMP_NEAR_NEARL2B] = 1200;
+#if !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAREST_NEWL2B] = 1500;
   rd->thresh_mult[THR_COMP_NEW_NEARESTL2B] = 1500;
+#endif  // !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAR_NEWL2B] = 1700;
   rd->thresh_mult[THR_COMP_NEW_NEARL2B] = 1700;
   rd->thresh_mult[THR_COMP_NEW_NEWL2B] = 2000;
   rd->thresh_mult[THR_COMP_GLOBAL_GLOBALL2B] = 2500;
 
   rd->thresh_mult[THR_COMP_NEAR_NEARL3B] = 1200;
+#if !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAREST_NEWL3B] = 1500;
   rd->thresh_mult[THR_COMP_NEW_NEARESTL3B] = 1500;
+#endif  // !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAR_NEWL3B] = 1870;
   rd->thresh_mult[THR_COMP_NEW_NEARL3B] = 1700;
   rd->thresh_mult[THR_COMP_NEW_NEWL3B] = 2000;
   rd->thresh_mult[THR_COMP_GLOBAL_GLOBALL3B] = 2500;
 
   rd->thresh_mult[THR_COMP_NEAR_NEARGB] = 1200;
+#if !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAREST_NEWGB] = 1500;
   rd->thresh_mult[THR_COMP_NEW_NEARESTGB] = 1500;
+#endif  // !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAR_NEWGB] = 1700;
   rd->thresh_mult[THR_COMP_NEW_NEARGB] = 1700;
   rd->thresh_mult[THR_COMP_NEW_NEWGB] = 2000;
   rd->thresh_mult[THR_COMP_GLOBAL_GLOBALGB] = 2500;
 
   rd->thresh_mult[THR_COMP_NEAR_NEARLA2] = 1200;
+#if !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAREST_NEWLA2] = 1800;
   rd->thresh_mult[THR_COMP_NEW_NEARESTLA2] = 1500;
+#endif  // !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAR_NEWLA2] = 1700;
   rd->thresh_mult[THR_COMP_NEW_NEARLA2] = 1700;
   rd->thresh_mult[THR_COMP_NEW_NEWLA2] = 2000;
   rd->thresh_mult[THR_COMP_GLOBAL_GLOBALLA2] = 2500;
 
   rd->thresh_mult[THR_COMP_NEAR_NEARL2A2] = 1200;
+#if !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAREST_NEWL2A2] = 1500;
   rd->thresh_mult[THR_COMP_NEW_NEARESTL2A2] = 1500;
+#endif  // !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAR_NEWL2A2] = 1700;
   rd->thresh_mult[THR_COMP_NEW_NEARL2A2] = 1700;
   rd->thresh_mult[THR_COMP_NEW_NEWL2A2] = 2000;
   rd->thresh_mult[THR_COMP_GLOBAL_GLOBALL2A2] = 2500;
 
   rd->thresh_mult[THR_COMP_NEAR_NEARL3A2] = 1440;
+#if !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAREST_NEWL3A2] = 1500;
   rd->thresh_mult[THR_COMP_NEW_NEARESTL3A2] = 1500;
+#endif  // !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAR_NEWL3A2] = 1700;
   rd->thresh_mult[THR_COMP_NEW_NEARL3A2] = 1700;
   rd->thresh_mult[THR_COMP_NEW_NEWL3A2] = 2000;
   rd->thresh_mult[THR_COMP_GLOBAL_GLOBALL3A2] = 2500;
 
   rd->thresh_mult[THR_COMP_NEAR_NEARGA2] = 1200;
+#if !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAREST_NEWGA2] = 1500;
   rd->thresh_mult[THR_COMP_NEW_NEARESTGA2] = 1500;
+#endif  // !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAR_NEWGA2] = 1700;
   rd->thresh_mult[THR_COMP_NEW_NEARGA2] = 1700;
   rd->thresh_mult[THR_COMP_NEW_NEWGA2] = 2000;
   rd->thresh_mult[THR_COMP_GLOBAL_GLOBALGA2] = 2750;
 
   rd->thresh_mult[THR_COMP_NEAR_NEARLL2] = 1600;
+#if !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAREST_NEWLL2] = 2000;
   rd->thresh_mult[THR_COMP_NEW_NEARESTLL2] = 2000;
+#endif  // !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAR_NEWLL2] = 2640;
   rd->thresh_mult[THR_COMP_NEW_NEARLL2] = 2200;
   rd->thresh_mult[THR_COMP_NEW_NEWLL2] = 2400;
   rd->thresh_mult[THR_COMP_GLOBAL_GLOBALLL2] = 3200;
 
   rd->thresh_mult[THR_COMP_NEAR_NEARLL3] = 1600;
+#if !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAREST_NEWLL3] = 2000;
   rd->thresh_mult[THR_COMP_NEW_NEARESTLL3] = 1800;
+#endif  // !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAR_NEWLL3] = 2200;
   rd->thresh_mult[THR_COMP_NEW_NEARLL3] = 2200;
   rd->thresh_mult[THR_COMP_NEW_NEWLL3] = 2400;
   rd->thresh_mult[THR_COMP_GLOBAL_GLOBALLL3] = 3200;
 
   rd->thresh_mult[THR_COMP_NEAR_NEARLG] = 1760;
+#if !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAREST_NEWLG] = 2400;
   rd->thresh_mult[THR_COMP_NEW_NEARESTLG] = 2000;
+#endif  // !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAR_NEWLG] = 1760;
   rd->thresh_mult[THR_COMP_NEW_NEARLG] = 2640;
   rd->thresh_mult[THR_COMP_NEW_NEWLG] = 2400;
   rd->thresh_mult[THR_COMP_GLOBAL_GLOBALLG] = 3200;
 
   rd->thresh_mult[THR_COMP_NEAR_NEARBA] = 1600;
+#if !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAREST_NEWBA] = 2000;
   rd->thresh_mult[THR_COMP_NEW_NEARESTBA] = 2000;
+
+#endif  // !CONFIG_NEW_INTER_MODES
   rd->thresh_mult[THR_COMP_NEAR_NEWBA] = 2200;
   rd->thresh_mult[THR_COMP_NEW_NEARBA] = 1980;
   rd->thresh_mult[THR_COMP_NEW_NEWBA] = 2640;
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index 3af3512..d313561 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -102,6 +102,145 @@
   4144,  4120,  4096
 };
 
+#if CONFIG_NEW_INTER_MODES
+static const THR_MODES av1_default_mode_order[MAX_MODES] = {
+  THR_NEARMV,
+  THR_NEARL2,
+  THR_NEARL3,
+  THR_NEARB,
+  THR_NEARA2,
+  THR_NEARA,
+  THR_NEARG,
+
+  THR_NEWMV,
+  THR_NEWL2,
+  THR_NEWL3,
+  THR_NEWB,
+  THR_NEWA2,
+  THR_NEWA,
+  THR_NEWG,
+
+  THR_GLOBALMV,
+  THR_GLOBALL2,
+  THR_GLOBALL3,
+  THR_GLOBALB,
+  THR_GLOBALA2,
+  THR_GLOBALG,
+  THR_GLOBALA,
+
+  THR_COMP_NEAR_NEARLA,
+  THR_COMP_NEAR_NEARL2A,
+  THR_COMP_NEAR_NEARL3A,
+  THR_COMP_NEAR_NEARGA,
+  THR_COMP_NEAR_NEARLB,
+  THR_COMP_NEAR_NEARL2B,
+  THR_COMP_NEAR_NEARL3B,
+  THR_COMP_NEAR_NEARGB,
+  THR_COMP_NEAR_NEARLA2,
+  THR_COMP_NEAR_NEARL2A2,
+  THR_COMP_NEAR_NEARL3A2,
+  THR_COMP_NEAR_NEARGA2,
+
+  THR_COMP_NEAR_NEARLL2,
+  THR_COMP_NEAR_NEARLL3,
+  THR_COMP_NEAR_NEARLG,
+  THR_COMP_NEAR_NEARBA,
+
+  THR_COMP_NEW_NEARLA,
+  THR_COMP_NEAR_NEWLA,
+  THR_COMP_NEW_NEWLA,
+  THR_COMP_GLOBAL_GLOBALLA,
+
+  THR_COMP_NEW_NEARL2A,
+  THR_COMP_NEAR_NEWL2A,
+  THR_COMP_NEW_NEWL2A,
+  THR_COMP_GLOBAL_GLOBALL2A,
+
+  THR_COMP_NEW_NEARL3A,
+  THR_COMP_NEAR_NEWL3A,
+  THR_COMP_NEW_NEWL3A,
+  THR_COMP_GLOBAL_GLOBALL3A,
+
+  THR_COMP_NEW_NEARGA,
+  THR_COMP_NEAR_NEWGA,
+  THR_COMP_NEW_NEWGA,
+  THR_COMP_GLOBAL_GLOBALGA,
+
+  THR_COMP_NEW_NEARLB,
+  THR_COMP_NEAR_NEWLB,
+  THR_COMP_NEW_NEWLB,
+  THR_COMP_GLOBAL_GLOBALLB,
+
+  THR_COMP_NEW_NEARL2B,
+  THR_COMP_NEAR_NEWL2B,
+  THR_COMP_NEW_NEWL2B,
+  THR_COMP_GLOBAL_GLOBALL2B,
+
+  THR_COMP_NEW_NEARL3B,
+  THR_COMP_NEAR_NEWL3B,
+  THR_COMP_NEW_NEWL3B,
+  THR_COMP_GLOBAL_GLOBALL3B,
+
+  THR_COMP_NEW_NEARGB,
+  THR_COMP_NEAR_NEWGB,
+  THR_COMP_NEW_NEWGB,
+  THR_COMP_GLOBAL_GLOBALGB,
+
+  THR_COMP_NEW_NEARLA2,
+  THR_COMP_NEAR_NEWLA2,
+  THR_COMP_NEW_NEWLA2,
+  THR_COMP_GLOBAL_GLOBALLA2,
+
+  THR_COMP_NEW_NEARL2A2,
+  THR_COMP_NEAR_NEWL2A2,
+  THR_COMP_NEW_NEWL2A2,
+  THR_COMP_GLOBAL_GLOBALL2A2,
+
+  THR_COMP_NEW_NEARL3A2,
+  THR_COMP_NEAR_NEWL3A2,
+  THR_COMP_NEW_NEWL3A2,
+  THR_COMP_GLOBAL_GLOBALL3A2,
+
+  THR_COMP_NEW_NEARGA2,
+  THR_COMP_NEAR_NEWGA2,
+  THR_COMP_NEW_NEWGA2,
+  THR_COMP_GLOBAL_GLOBALGA2,
+
+  THR_COMP_NEW_NEARLL2,
+  THR_COMP_NEAR_NEWLL2,
+  THR_COMP_NEW_NEWLL2,
+  THR_COMP_GLOBAL_GLOBALLL2,
+
+  THR_COMP_NEW_NEARLL3,
+  THR_COMP_NEAR_NEWLL3,
+  THR_COMP_NEW_NEWLL3,
+  THR_COMP_GLOBAL_GLOBALLL3,
+
+  THR_COMP_NEW_NEARLG,
+  THR_COMP_NEAR_NEWLG,
+  THR_COMP_NEW_NEWLG,
+  THR_COMP_GLOBAL_GLOBALLG,
+
+  THR_COMP_NEW_NEARBA,
+  THR_COMP_NEAR_NEWBA,
+  THR_COMP_NEW_NEWBA,
+  THR_COMP_GLOBAL_GLOBALBA,
+
+  THR_DC,
+  THR_PAETH,
+  THR_SMOOTH,
+  THR_SMOOTH_V,
+  THR_SMOOTH_H,
+  THR_H_PRED,
+  THR_V_PRED,
+  THR_D135_PRED,
+  THR_D203_PRED,
+  THR_D157_PRED,
+  THR_D67_PRED,
+  THR_D113_PRED,
+  THR_D45_PRED,
+};
+#else
 static const THR_MODES av1_default_mode_order[MAX_MODES] = {
   THR_NEARESTMV,
   THR_NEARESTL2,
@@ -294,6 +433,7 @@
   THR_D113_PRED,
   THR_D45_PRED,
 };
+#endif  // CONFIG_NEW_INTER_MODES
 
 /*!\cond */
 typedef struct SingleInterModeState {
@@ -722,8 +862,10 @@
       return mode_cost;
     } else {
       mode_cost += mode_costs->zeromv_mode_cost[mode_ctx][1];
+#if !CONFIG_NEW_INTER_MODES
       mode_ctx = (mode_context >> REFMV_OFFSET) & REFMV_CTX_MASK;
       mode_cost += mode_costs->refmv_mode_cost[mode_ctx][mode != NEARESTMV];
+#endif  // !CONFIG_NEW_INTER_MODES
       return mode_cost;
     }
   }
@@ -983,6 +1125,10 @@
   clamp_mv(mv, &mv_limits);
 }
 
+#if !CONFIG_NEW_INTER_MODES
+/* Because NEARESTMV is gone with NEW_INTER_MODES and there is no easy way to
+ * check if GLOBALMV and NEARMV are using the same MV, this function should not
+ * be called.*/
 /* If the current mode shares the same mv with other modes with higher cost,
  * skip this mode. */
 static int skip_repeated_mv(const AV1_COMMON *const cm,
@@ -1040,6 +1186,7 @@
   }
   return 0;
 }
+#endif  // !CONFIG_NEW_INTER_MODES
 
 static INLINE int clamp_and_check_mv(int_mv *out_mv, int_mv in_mv,
                                      const AV1_COMMON *cm,
@@ -1117,7 +1264,11 @@
               x->mv_costs.mv_cost_stack, MV_COST_WEIGHT);
         }
       }
+#if CONFIG_NEW_INTER_MODES
+    } else if (this_mode == NEAR_NEWMV) {
+#else
     } else if (this_mode == NEAREST_NEWMV || this_mode == NEAR_NEWMV) {
+#endif  // CONFIG_NEW_INTER_MODES
       if (valid_mv1) {
         cur_mv[1].as_int = args->single_newmv[ref_mv_idx][refs[1]].as_int;
         clamp_mv_in_range(x, &cur_mv[1], 1);
@@ -1135,7 +1286,11 @@
                                    x->mv_costs.mv_cost_stack, MV_COST_WEIGHT);
       }
     } else {
+#if CONFIG_NEW_INTER_MODES
+      assert(this_mode == NEW_NEARMV);
+#else
       assert(this_mode == NEW_NEARESTMV || this_mode == NEW_NEARMV);
+#endif  // CONFIG_NEW_INTER_MODES
       if (valid_mv0) {
         cur_mv[0].as_int = args->single_newmv[ref_mv_idx][refs[0]].as_int;
         clamp_mv_in_range(x, &cur_mv[0], 0);
@@ -1710,6 +1865,7 @@
   return 0;
 }
 
+#if !CONFIG_NEW_INTER_MODES
 // Check NEARESTMV, NEARMV, GLOBALMV ref mvs for duplicate and skip the relevant
 // mode
 static INLINE int check_repeat_ref_mv(const MB_MODE_INFO_EXT *mbmi_ext,
@@ -1748,25 +1904,36 @@
   }
   return 0;
 }
+#endif  // !CONFIG_NEW_INTER_MODES
 
 static INLINE int get_this_mv(int_mv *this_mv, PREDICTION_MODE this_mode,
                               int ref_idx, int ref_mv_idx,
                               int skip_repeated_ref_mv,
                               const MV_REFERENCE_FRAME *ref_frame,
                               const MB_MODE_INFO_EXT *mbmi_ext) {
+#if CONFIG_NEW_INTER_MODES
+  (void)skip_repeated_ref_mv;
+#endif  // CONFIG_NEW_INTER_MODES
   const PREDICTION_MODE single_mode = get_single_mode(this_mode, ref_idx);
   assert(is_inter_singleref_mode(single_mode));
   if (single_mode == NEWMV) {
     this_mv->as_int = INVALID_MV;
   } else if (single_mode == GLOBALMV) {
+#if !CONFIG_NEW_INTER_MODES
     if (skip_repeated_ref_mv &&
         check_repeat_ref_mv(mbmi_ext, ref_idx, ref_frame, single_mode))
       return 0;
+#endif  // !CONFIG_NEW_INTER_MODES
     *this_mv = mbmi_ext->global_mvs[ref_frame[ref_idx]];
   } else {
+#if CONFIG_NEW_INTER_MODES
+    assert(single_mode == NEARMV);
+    const int ref_mv_offset = ref_mv_idx;
+#else
     assert(single_mode == NEARMV || single_mode == NEARESTMV);
-    const uint8_t ref_frame_type = av1_ref_frame_type(ref_frame);
     const int ref_mv_offset = single_mode == NEARESTMV ? 0 : ref_mv_idx + 1;
+#endif  // CONFIG_NEW_INTER_MODES
+    const uint8_t ref_frame_type = av1_ref_frame_type(ref_frame);
     if (ref_mv_offset < mbmi_ext->ref_mv_count[ref_frame_type]) {
       assert(ref_mv_offset >= 0);
       if (ref_idx == 0) {
@@ -1777,9 +1944,11 @@
             mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_offset].comp_mv;
       }
     } else {
+#if !CONFIG_NEW_INTER_MODES
       if (skip_repeated_ref_mv &&
           check_repeat_ref_mv(mbmi_ext, ref_idx, ref_frame, single_mode))
         return 0;
+#endif  // !CONFIG_NEW_INTER_MODES
       *this_mv = mbmi_ext->global_mvs[ref_frame[ref_idx]];
     }
   }
@@ -1816,13 +1985,54 @@
   return ret;
 }
 
+#if CONFIG_NEW_INTER_MODES
+// See write_drl_idx for a description of how this works.
+// With CONFIG_NEW_INTER_MODES, this computes the bit cost
+// of writing the full 4-value DRL index instead of the
+// 3-value index that was used for NEARMV before.  This will
+// also guarantee a DRL cost of zero if the mode does not need
+// a DRL index.
+static INLINE int get_drl_cost(const MB_MODE_INFO *mbmi,
+                               const MB_MODE_INFO_EXT *mbmi_ext,
+                               const MACROBLOCK *x, int8_t ref_frame_type) {
+  assert(mbmi->ref_mv_idx < MAX_DRL_BITS + 1);
+  if (!have_drl_index(mbmi->mode)) {
+    return 0;
+  }
+  int16_t mode_ctx =
+      av1_mode_context_analyzer(mbmi_ext->mode_context, mbmi->ref_frame);
+  (void)mode_ctx;  // This is here for future experiments
+  int cost = 0;
+  const int range =
+      AOMMIN(mbmi_ext->ref_mv_count[ref_frame_type] - 1, MAX_DRL_BITS);
+  for (int idx = 0; idx < range; ++idx) {
+    uint8_t drl_ctx = av1_drl_ctx(mbmi_ext->weight[ref_frame_type], idx);
+    switch (idx) {
+      case 0:
+        cost +=
+            x->mode_costs.drl_mode_cost[0][drl_ctx][mbmi->ref_mv_idx != idx];
+        break;
+      case 1:
+        cost +=
+            x->mode_costs.drl_mode_cost[1][drl_ctx][mbmi->ref_mv_idx != idx];
+        break;
+      default:
+        cost +=
+            x->mode_costs.drl_mode_cost[2][drl_ctx][mbmi->ref_mv_idx != idx];
+        break;
+    }
+    if (mbmi->ref_mv_idx == idx) return cost;
+  }
+  return cost;
+}
+#else
 static INLINE int get_drl_cost(const MB_MODE_INFO *mbmi,
                                const MB_MODE_INFO_EXT *mbmi_ext,
                                const int (*const drl_mode_cost0)[2],
                                int8_t ref_frame_type) {
   int cost = 0;
   if (mbmi->mode == NEWMV || mbmi->mode == NEW_NEWMV) {
-    for (int idx = 0; idx < 2; ++idx) {
+    for (int idx = 0; idx < MAX_DRL_BITS; ++idx) {
       if (mbmi_ext->ref_mv_count[ref_frame_type] > idx + 1) {
         uint8_t drl_ctx = av1_drl_ctx(mbmi_ext->weight[ref_frame_type], idx);
         cost += drl_mode_cost0[drl_ctx][mbmi->ref_mv_idx != idx];
@@ -1833,7 +2043,7 @@
   }
 
   if (have_nearmv_in_inter_mode(mbmi->mode)) {
-    for (int idx = 1; idx < 3; ++idx) {
+    for (int idx = 1; idx < MAX_DRL_BITS + 1; ++idx) {
       if (mbmi_ext->ref_mv_count[ref_frame_type] > idx + 1) {
         uint8_t drl_ctx = av1_drl_ctx(mbmi_ext->weight[ref_frame_type], idx);
         cost += drl_mode_cost0[drl_ctx][mbmi->ref_mv_idx != (idx - 1)];
@@ -1844,6 +2054,7 @@
   }
   return cost;
 }
+#endif  // CONFIG_NEW_INTER_MODES
 
 static INLINE int is_single_newmv_valid(const HandleInterModeArgs *const args,
                                         const MB_MODE_INFO *const mbmi,
@@ -1863,6 +2074,20 @@
                                const MV_REFERENCE_FRAME *ref_frame,
                                PREDICTION_MODE mode) {
   MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
+#if CONFIG_NEW_INTER_MODES
+  // Get the count of reference vectors availiable to this mode.
+  // For NEAR and NEW, this is the min of the number of MVs available
+  // in the frame and MAX_REF_MV_SEARCH.
+  // For GLOBALMV, this is 1: the frame global motion vector always exists.
+  int has_drl = have_drl_index(mode);
+  if (!has_drl) {
+    assert(mode == GLOBALMV || mode == GLOBAL_GLOBALMV);
+    return 1;
+  }
+  const int8_t ref_frame_type = av1_ref_frame_type(ref_frame);
+  int ref_mv_count = mbmi_ext->ref_mv_count[ref_frame_type];
+  return AOMMIN(MAX_REF_MV_SEARCH, ref_mv_count);
+#else
   const int8_t ref_frame_type = av1_ref_frame_type(ref_frame);
   const int has_nearmv = have_nearmv_in_inter_mode(mode) ? 1 : 0;
   const int ref_mv_count = mbmi_ext->ref_mv_count[ref_frame_type];
@@ -1873,6 +2098,7 @@
       has_drl ? AOMMIN(MAX_REF_MV_SEARCH, ref_mv_count - has_nearmv) : 1;
 
   return ref_set;
+#endif  // CONFIG_NEW_INTER_MODES
 }
 
 // Whether this reference motion vector can be skipped, based on initial
@@ -1892,7 +2118,11 @@
         mbmi->ref_frame[0] == LAST3_FRAME ||
         mbmi->ref_frame[1] == LAST2_FRAME ||
         mbmi->ref_frame[1] == LAST3_FRAME) {
+#if CONFIG_NEW_INTER_MODES
+      const int has_nearmv = 0;
+#else
       const int has_nearmv = have_nearmv_in_inter_mode(mbmi->mode) ? 1 : 0;
+#endif  // CONFIG_NEW_INTER_MODES
       if (mbmi_ext->weight[ref_frame_type][ref_mv_idx + has_nearmv] <
           REF_CAT_LEVEL) {
         return true;
@@ -1903,7 +2133,11 @@
         have_newmv_in_inter_mode(mbmi->mode)) {
       if (mbmi->ref_frame[0] != ref_frame_dist_info->nearest_past_ref &&
           mbmi->ref_frame[0] != ref_frame_dist_info->nearest_future_ref) {
+#if CONFIG_NEW_INTER_MODES
+        const int has_nearmv = 0;
+#else
         const int has_nearmv = have_nearmv_in_inter_mode(mbmi->mode) ? 1 : 0;
+#endif  // CONFIG_NEW_INTER_MODES
         if (mbmi_ext->weight[ref_frame_type][ref_mv_idx + has_nearmv] <
             REF_CAT_LEVEL) {
           return true;
@@ -1917,13 +2151,23 @@
     return true;
   }
   size_t est_rd_rate = args->ref_frame_cost + args->single_comp_cost;
+#if CONFIG_NEW_INTER_MODES
+  const int drl_cost = get_drl_cost(mbmi, mbmi_ext, x, ref_frame_type);
+#else
   const int drl_cost = get_drl_cost(
       mbmi, mbmi_ext, x->mode_costs.drl_mode_cost0, ref_frame_type);
+#endif  // CONFIG_NEW_INTER_MODES
   est_rd_rate += drl_cost;
+#if CONFIG_NEW_INTER_MODES
+  if (RDCOST(x->rdmult, est_rd_rate, 0) > ref_best_rd) {
+    return true;
+  }
+#else
   if (RDCOST(x->rdmult, est_rd_rate, 0) > ref_best_rd &&
       mbmi->mode != NEARESTMV && mbmi->mode != NEAREST_NEARESTMV) {
     return true;
   }
+#endif  // CONFIG_NEW_INTER_MODES
   return false;
 }
 
@@ -1961,8 +2205,12 @@
   mbmi->ref_mv_idx = ref_mv_idx;
 
   rd_stats->rate += args->ref_frame_cost + args->single_comp_cost;
+#if CONFIG_NEW_INTER_MODES
+  const int drl_cost = get_drl_cost(mbmi, mbmi_ext, x, ref_frame_type);
+#else
   const int drl_cost =
       get_drl_cost(mbmi, mbmi_ext, mode_costs->drl_mode_cost0, ref_frame_type);
+#endif  // CONFIG_NEW_INTER_MODES
   rd_stats->rate += drl_cost;
   mode_info[ref_mv_idx].drl_cost = drl_cost;
 
@@ -2026,8 +2274,16 @@
   const PREDICTION_MODE this_mode = mbmi->mode;
 
   // Only search indices if they have some chance of being good.
+#if CONFIG_NEW_INTER_MODES
+  int good_indices = 0x1;  // Always allow the zeroth MV to be searched
+  const int start_mv_idx =
+      1;  // Because MV 0 will be returned, don't waste time on it here
+#else
   int good_indices = 0;
-  for (int i = 0; i < ref_set; ++i) {
+  const int start_mv_idx = 0;
+#endif  // CONFIG_NEW_INTER_MODES
+
+  for (int i = start_mv_idx; i < ref_set; ++i) {
     if (ref_mv_idx_early_breakout(&cpi->sf, &cpi->ref_frame_dist_info, x, args,
                                   ref_best_rd, i)) {
       continue;
@@ -2051,8 +2307,13 @@
   }
 
   // Calculate the RD cost for the motion vectors using simple translation.
+#if CONFIG_NEW_INTER_MODES
+  int64_t idx_rdcost[MAX_REF_MV_SEARCH];
+  for (int i = 0; i < MAX_REF_MV_SEARCH; i++) idx_rdcost[i] = INT64_MAX;
+#else
   int64_t idx_rdcost[] = { INT64_MAX, INT64_MAX, INT64_MAX };
-  for (int ref_mv_idx = 0; ref_mv_idx < ref_set; ++ref_mv_idx) {
+#endif  // CONFIG_NEW_INTER_MODES
+  for (int ref_mv_idx = start_mv_idx; ref_mv_idx < ref_set; ++ref_mv_idx) {
     // If this index is bad, ignore it.
     if (!mask_check_bit(good_indices, ref_mv_idx)) {
       continue;
@@ -2061,8 +2322,8 @@
         cpi, x, rd_stats, args, ref_mv_idx, mode_info, ref_best_rd, bsize);
   }
   // Find the index with the best RD cost.
-  int best_idx = 0;
-  for (int i = 1; i < MAX_REF_MV_SEARCH; ++i) {
+  int best_idx = start_mv_idx;
+  for (int i = start_mv_idx + 1; i < MAX_REF_MV_SEARCH; ++i) {
     if (idx_rdcost[i] < idx_rdcost[best_idx]) {
       best_idx = i;
     }
@@ -2072,8 +2333,12 @@
   // If the simple translation cost is not within this multiple of the
   // best RD, skip it. Note that the cutoff is derived experimentally.
   const double ref_dth = 5;
+#if CONFIG_NEW_INTER_MODES
+  int result = 0x1;  // Always allow the zeroth MV to be searched
+#else
   int result = 0;
-  for (int i = 0; i < ref_set; ++i) {
+#endif  // CONFIG_NEW_INTER_MODES
+  for (int i = start_mv_idx; i < ref_set; ++i) {
     if (mask_check_bit(good_indices, i) &&
         (1.0 * idx_rdcost[i]) / idx_rdcost[best_idx] < dth &&
         (1.0 * idx_rdcost[i]) / ref_best_rd < ref_dth) {
@@ -2749,8 +3014,12 @@
 
     // Compute cost for signalling this DRL index
     rd_stats->rate = base_rate;
+#if CONFIG_NEW_INTER_MODES
+    const int drl_cost = get_drl_cost(mbmi, mbmi_ext, x, ref_frame_type);
+#else
     const int drl_cost = get_drl_cost(
         mbmi, mbmi_ext, mode_costs->drl_mode_cost0, ref_frame_type);
+#endif  // CONFIG_NEW_INTER_MODES
     rd_stats->rate += drl_cost;
     mode_info[ref_mv_idx].drl_cost = drl_cost;
 
@@ -2798,10 +3067,19 @@
       mbmi->mv[i].as_int = cur_mv[i].as_int;
     }
 
+#if CONFIG_NEW_INTER_MODES
+    const int like_nearest =
+        (mbmi->mode == NEARMV || mbmi->mode == NEAR_NEARMV) &&
+        mbmi->ref_mv_idx == 0;
+    if (RDCOST(x->rdmult, rd_stats->rate, 0) > ref_best_rd && !like_nearest) {
+      continue;
+    }
+#else
     if (RDCOST(x->rdmult, rd_stats->rate, 0) > ref_best_rd &&
         mbmi->mode != NEARESTMV && mbmi->mode != NEAREST_NEARESTMV) {
       continue;
     }
+#endif  // CONFIG_NEW_INTER_MODES
 
     // Skip the rest of the search if prune_ref_mv_idx_search speed feature
     // is enabled, and the current MV is similar to a previous one.
@@ -2944,6 +3222,7 @@
   av1_copy_array(xd->tx_type_map, best_tx_type_map, xd->height * xd->width);
 
   rd_stats->rdcost = RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist);
+  assert(av1_check_newmv_joint_nonzero(cm, x));
 
   return rd_stats->rdcost;
 }
@@ -2993,9 +3272,16 @@
   // TODO(Ravi): Populate mbmi_ext->ref_mv_stack[ref_frame][4] and
   // mbmi_ext->weight[ref_frame][4] inside av1_find_mv_refs.
   av1_copy_usable_ref_mv_stack_and_weight(xd, mbmi_ext, ref_frame);
+
+#if CONFIG_NEW_INTER_MODES
+  int_mv dv_ref = av1_find_best_ref_mv_from_stack(
+      /*allow_hp=*/0, mbmi_ext, ref_frame, /*is_integer=*/0);
+  dv_ref.as_int = dv_ref.as_int == INVALID_MV ? 0 : dv_ref.as_int;
+#else
   int_mv nearestmv, nearmv;
-  av1_find_best_ref_mvs_from_stack(0, mbmi_ext, ref_frame, &nearestmv, &nearmv,
-                                   0);
+  av1_find_best_ref_mvs_from_stack(
+      /*allow_hp=*/0, mbmi_ext, ref_frame, &nearestmv, &nearmv,
+      /*is_integer=*/0);
 
   if (nearestmv.as_int == INVALID_MV) {
     nearestmv.as_int = 0;
@@ -3005,6 +3291,7 @@
   }
 
   int_mv dv_ref = nearestmv.as_int == 0 ? nearmv : nearestmv;
+#endif  // CONFIG_NEW_INTER_MODES
   if (dv_ref.as_int == 0) {
     av1_find_ref_dv(&dv_ref, tile, cm->seq_params.mib_size, mi_row);
   }
@@ -3168,6 +3455,7 @@
 #if CONFIG_RD_DEBUG
   mbmi->rd_stats = *rd_stats;
 #endif
+  assert(av1_check_newmv_joint_nonzero(cm, x));
   return best_rd;
 }
 
@@ -3302,7 +3590,12 @@
       LAST_FRAME + skip_mode_info->ref_frame_idx_0;
   const MV_REFERENCE_FRAME second_ref_frame =
       LAST_FRAME + skip_mode_info->ref_frame_idx_1;
+
+#if CONFIG_NEW_INTER_MODES
+  const PREDICTION_MODE this_mode = NEAR_NEARMV;
+#else
   const PREDICTION_MODE this_mode = NEAREST_NEARESTMV;
+#endif  // CONFIG_NEW_INTER_MODES
   const THR_MODES mode_index =
       get_prediction_mode_idx(this_mode, ref_frame, second_ref_frame);
 
@@ -3317,6 +3610,9 @@
   }
 
   mbmi->mode = this_mode;
+#if CONFIG_NEW_INTER_MODES
+  mbmi->ref_mv_idx = 0;
+#endif  // CONFIG_NEW_INTER_MODES
   mbmi->uv_mode = UV_DC_PRED;
   mbmi->ref_frame[0] = ref_frame;
   mbmi->ref_frame[1] = second_ref_frame;
@@ -3335,8 +3631,15 @@
     av1_copy_usable_ref_mv_stack_and_weight(xd, mbmi_ext, ref_frame_type);
   }
 
+#if CONFIG_NEW_INTER_MODES
+  assert(this_mode == NEAR_NEARMV);
+  assert(mbmi->mode == NEAR_NEARMV);
+  assert(mbmi->ref_mv_idx == 0);
+#else
   assert(this_mode == NEAREST_NEARESTMV);
+#endif  // CONFIG_NEW_INTER_MODES
   if (!build_cur_mv(mbmi->mv, this_mode, cm, x, 0)) {
+    assert(av1_check_newmv_joint_nonzero(cm, x));
     return;
   }
 
@@ -3395,7 +3698,11 @@
     search_state->best_mbmode.skip_mode = search_state->best_mbmode.skip_txfm =
         1;
 #endif
+#if CONFIG_NEW_INTER_MODES
+    search_state->best_mbmode.mode = NEAR_NEARMV;
+#else
     search_state->best_mbmode.mode = NEAREST_NEARESTMV;
+#endif  // CONFIG_NEW_INTER_MODES
     search_state->best_mbmode.ref_frame[0] = mbmi->ref_frame[0];
     search_state->best_mbmode.ref_frame[1] = mbmi->ref_frame[1];
     search_state->best_mbmode.mv[0].as_int = mbmi->mv[0].as_int;
@@ -3450,6 +3757,7 @@
 
     x->txfm_search_info.skip_txfm = 1;
   }
+  assert(av1_check_newmv_joint_nonzero(cm, x));
 }
 
 // Get winner mode stats of given mode index
@@ -3767,15 +4075,17 @@
 
       mask->pred_modes[ALTREF_FRAME] = ~INTER_NEAREST_NEAR_ZERO;
       const MV_REFERENCE_FRAME tmp_ref_frames[2] = { ALTREF_FRAME, NONE_FRAME };
-      int_mv near_mv, nearest_mv, global_mv;
-      get_this_mv(&nearest_mv, NEARESTMV, 0, 0, 0, tmp_ref_frames, x->mbmi_ext);
+      int_mv near_mv, global_mv;
       get_this_mv(&near_mv, NEARMV, 0, 0, 0, tmp_ref_frames, x->mbmi_ext);
       get_this_mv(&global_mv, GLOBALMV, 0, 0, 0, tmp_ref_frames, x->mbmi_ext);
-
       if (near_mv.as_int != global_mv.as_int)
         mask->pred_modes[ALTREF_FRAME] |= (1 << NEARMV);
+#if !CONFIG_NEW_INTER_MODES
+      int_mv nearest_mv;
+      get_this_mv(&nearest_mv, NEARESTMV, 0, 0, 0, tmp_ref_frames, x->mbmi_ext);
       if (nearest_mv.as_int != global_mv.as_int)
         mask->pred_modes[ALTREF_FRAME] |= (1 << NEARESTMV);
+#endif  // !CONFIG_NEW_INTER_MODES
     }
   }
 
@@ -4151,10 +4461,12 @@
       ref_frame[0] == INTRA_FRAME)
     return 1;
 
+#if !CONFIG_NEW_INTER_MODES
   const AV1_COMMON *const cm = &cpi->common;
   if (skip_repeated_mv(cm, x, mode, ref_frame, search_state)) {
     return 1;
   }
+#endif  // !CONFIG_NEW_INTER_MODES
 
   const MB_MODE_INFO *const mbmi = x->e_mbd.mi[0];
   // If no valid mode has been found so far in PARTITION_NONE when finding a
@@ -4422,9 +4734,15 @@
 
   const int ref_set = get_drl_refmv_count(x, refs, this_mode);
   for (i = 0; i < 2; ++i) {
+#if CONFIG_NEW_INTER_MODES
+    if (!ref_searched[i] || (mode[i] != NEARMV)) {
+      continue;
+    }
+#else
     if (!ref_searched[i] || (mode[i] != NEARESTMV && mode[i] != NEARMV)) {
       continue;
     }
+#endif  // CONFIG_NEW_INTER_MODES
     const MV_REFERENCE_FRAME single_refs[2] = { refs[i], NONE_FRAME };
     for (int ref_mv_idx = 0; ref_mv_idx < ref_set; ref_mv_idx++) {
       int_mv single_mv;
@@ -4481,9 +4799,12 @@
     MACROBLOCKD *const xd, const PREDICTION_MODE this_mode,
     const MV_REFERENCE_FRAME *ref_frames, int prune_compound_using_neighbors) {
   // Exclude non-extended compound modes from pruning
-  if (this_mode == NEAREST_NEARESTMV || this_mode == NEAR_NEARMV ||
-      this_mode == NEW_NEWMV || this_mode == GLOBAL_GLOBALMV)
+  if (this_mode == NEAR_NEARMV || this_mode == NEW_NEWMV ||
+      this_mode == GLOBAL_GLOBALMV)
     return 0;
+#if !CONFIG_NEW_INTER_MODES
+  if (this_mode == NEAREST_NEARESTMV) return 0;
+#endif
 
   int is_ref_match[2] = { 0 };  // 0 - match for forward refs
                                 // 1 - match for backward refs
@@ -4520,11 +4841,14 @@
     const PREDICTION_MODE *best_single_mode,
     int prune_comp_using_best_single_mode_ref) {
   // Exclude non-extended compound modes from pruning
-  if (this_mode == NEAREST_NEARESTMV || this_mode == NEAR_NEARMV ||
-      this_mode == NEW_NEWMV || this_mode == GLOBAL_GLOBALMV)
+  if (this_mode == NEAR_NEARMV || this_mode == NEW_NEWMV ||
+      this_mode == GLOBAL_GLOBALMV)
     return 0;
-
+#if !CONFIG_NEW_INTER_MODES
+  if (this_mode == NEAREST_NEARESTMV) return 0;
   assert(this_mode >= NEAREST_NEWMV && this_mode <= NEW_NEARMV);
+#endif  // !CONFIG_NEW_INTER_MODES
+
   const PREDICTION_MODE comp_mode_ref0 = compound_ref0_mode(this_mode);
   // Get ref frame direction corresponding to NEWMV
   // 0 - NEWMV corresponding to forward direction
@@ -5620,9 +5944,10 @@
                               sf->inter_sf.adaptive_rd_thresh, bsize,
                               search_state.best_mode_index);
   }
-
   // macroblock modes
   *mbmi = search_state.best_mbmode;
+  assert(av1_check_newmv_joint_nonzero(cm, x));
+
   txfm_info->skip_txfm |= search_state.best_skip2;
 
   // Note: this section is needed since the mode may have been forced to
diff --git a/av1/encoder/rdopt_data_defs.h b/av1/encoder/rdopt_data_defs.h
index ca7ef81..995c213 100644
--- a/av1/encoder/rdopt_data_defs.h
+++ b/av1/encoder/rdopt_data_defs.h
@@ -35,9 +35,11 @@
 /* clang-format off */
 static const THR_MODES single_inter_to_mode_idx[SINGLE_INTER_MODE_NUM]
     [REF_FRAMES] = {
+#if !CONFIG_NEW_INTER_MODES
     // NEARESTMV,
         { THR_INVALID, THR_NEARESTMV, THR_NEARESTL2, THR_NEARESTL3,
         THR_NEARESTG, THR_NEARESTB, THR_NEARESTA2, THR_NEARESTA, },
+#endif  // !CONFIG_NEW_INTER_MODES
         // NEARMV,
         { THR_INVALID, THR_NEARMV, THR_NEARL2, THR_NEARL3,
         THR_NEARG, THR_NEARB, THR_NEARA2, THR_NEARA, },
@@ -53,6 +55,7 @@
 /* clang-format off */
 static const THR_MODES comp_inter_to_mode_idx[COMP_INTER_MODE_NUM][REF_FRAMES]
     [REF_FRAMES] = {
+#if !CONFIG_NEW_INTER_MODES
     // NEAREST_NEARESTMV,
         {
             { THR_INVALID, THR_INVALID, THR_INVALID, THR_INVALID, THR_INVALID,
@@ -82,6 +85,7 @@
             { THR_INVALID, THR_INVALID, THR_INVALID, THR_INVALID, THR_INVALID,
             THR_INVALID, THR_INVALID, THR_INVALID, },
         },
+#endif  // CONFIG_NEW_INTER_MODES
         // NEAR_NEARMV,
         {
             { THR_INVALID, THR_INVALID, THR_INVALID, THR_INVALID, THR_INVALID,
@@ -111,6 +115,7 @@
             { THR_INVALID, THR_INVALID, THR_INVALID, THR_INVALID, THR_INVALID,
             THR_INVALID, THR_INVALID, THR_INVALID, },
         },
+#if !CONFIG_NEW_INTER_MODES
         // NEAREST_NEWMV,
         {
             { THR_INVALID, THR_INVALID, THR_INVALID, THR_INVALID, THR_INVALID,
@@ -169,6 +174,7 @@
             { THR_INVALID, THR_INVALID, THR_INVALID, THR_INVALID, THR_INVALID,
             THR_INVALID, THR_INVALID, THR_INVALID, },
         },
+#endif  // CONFIG_NEW_INTER_MODES
         // NEAR_NEWMV,
         {
             { THR_INVALID, THR_INVALID, THR_INVALID, THR_INVALID, THR_INVALID,
diff --git a/av1/encoder/rdopt_utils.h b/av1/encoder/rdopt_utils.h
index 9e9f77d..64d215e 100644
--- a/av1/encoder/rdopt_utils.h
+++ b/av1/encoder/rdopt_utils.h
@@ -22,7 +22,7 @@
 extern "C" {
 #endif
 
-#define MAX_REF_MV_SEARCH 3
+#define MAX_REF_MV_SEARCH (MAX_DRL_BITS + 1)
 #define INTER_INTRA_RD_THRESH_SCALE 9
 #define INTER_INTRA_RD_THRESH_SHIFT 4
 
@@ -33,6 +33,147 @@
 
 // This array defines the mapping from the enums in THR_MODES to the actual
 // prediction modes and refrence frames
+#if CONFIG_NEW_INTER_MODES
+static const MODE_DEFINITION av1_mode_defs[MAX_MODES] = {
+  { NEARMV, { LAST_FRAME, NONE_FRAME } },
+  { NEARMV, { LAST2_FRAME, NONE_FRAME } },
+  { NEARMV, { LAST3_FRAME, NONE_FRAME } },
+  { NEARMV, { BWDREF_FRAME, NONE_FRAME } },
+  { NEARMV, { ALTREF2_FRAME, NONE_FRAME } },
+  { NEARMV, { ALTREF_FRAME, NONE_FRAME } },
+  { NEARMV, { GOLDEN_FRAME, NONE_FRAME } },
+
+  { NEWMV, { LAST_FRAME, NONE_FRAME } },
+  { NEWMV, { LAST2_FRAME, NONE_FRAME } },
+  { NEWMV, { LAST3_FRAME, NONE_FRAME } },
+  { NEWMV, { BWDREF_FRAME, NONE_FRAME } },
+  { NEWMV, { ALTREF2_FRAME, NONE_FRAME } },
+  { NEWMV, { ALTREF_FRAME, NONE_FRAME } },
+  { NEWMV, { GOLDEN_FRAME, NONE_FRAME } },
+
+  { GLOBALMV, { LAST_FRAME, NONE_FRAME } },
+  { GLOBALMV, { LAST2_FRAME, NONE_FRAME } },
+  { GLOBALMV, { LAST3_FRAME, NONE_FRAME } },
+  { GLOBALMV, { BWDREF_FRAME, NONE_FRAME } },
+  { GLOBALMV, { ALTREF2_FRAME, NONE_FRAME } },
+  { GLOBALMV, { GOLDEN_FRAME, NONE_FRAME } },
+  { GLOBALMV, { ALTREF_FRAME, NONE_FRAME } },
+
+  // TODO(zoeliu): May need to reconsider the order on the modes to check
+  { NEAR_NEARMV, { LAST_FRAME, ALTREF_FRAME } },
+  { NEAR_NEARMV, { LAST2_FRAME, ALTREF_FRAME } },
+  { NEAR_NEARMV, { LAST3_FRAME, ALTREF_FRAME } },
+  { NEAR_NEARMV, { GOLDEN_FRAME, ALTREF_FRAME } },
+  { NEAR_NEARMV, { LAST_FRAME, BWDREF_FRAME } },
+  { NEAR_NEARMV, { LAST2_FRAME, BWDREF_FRAME } },
+  { NEAR_NEARMV, { LAST3_FRAME, BWDREF_FRAME } },
+  { NEAR_NEARMV, { GOLDEN_FRAME, BWDREF_FRAME } },
+  { NEAR_NEARMV, { LAST_FRAME, ALTREF2_FRAME } },
+  { NEAR_NEARMV, { LAST2_FRAME, ALTREF2_FRAME } },
+  { NEAR_NEARMV, { LAST3_FRAME, ALTREF2_FRAME } },
+  { NEAR_NEARMV, { GOLDEN_FRAME, ALTREF2_FRAME } },
+
+  { NEAR_NEARMV, { LAST_FRAME, LAST2_FRAME } },
+  { NEAR_NEARMV, { LAST_FRAME, LAST3_FRAME } },
+  { NEAR_NEARMV, { LAST_FRAME, GOLDEN_FRAME } },
+  { NEAR_NEARMV, { BWDREF_FRAME, ALTREF_FRAME } },
+
+  { NEW_NEARMV, { LAST_FRAME, ALTREF_FRAME } },
+  { NEAR_NEWMV, { LAST_FRAME, ALTREF_FRAME } },
+  { NEW_NEWMV, { LAST_FRAME, ALTREF_FRAME } },
+  { GLOBAL_GLOBALMV, { LAST_FRAME, ALTREF_FRAME } },
+
+  { NEW_NEARMV, { LAST2_FRAME, ALTREF_FRAME } },
+  { NEAR_NEWMV, { LAST2_FRAME, ALTREF_FRAME } },
+  { NEW_NEWMV, { LAST2_FRAME, ALTREF_FRAME } },
+  { GLOBAL_GLOBALMV, { LAST2_FRAME, ALTREF_FRAME } },
+
+  { NEW_NEARMV, { LAST3_FRAME, ALTREF_FRAME } },
+  { NEAR_NEWMV, { LAST3_FRAME, ALTREF_FRAME } },
+  { NEW_NEWMV, { LAST3_FRAME, ALTREF_FRAME } },
+  { GLOBAL_GLOBALMV, { LAST3_FRAME, ALTREF_FRAME } },
+
+  { NEW_NEARMV, { GOLDEN_FRAME, ALTREF_FRAME } },
+  { NEAR_NEWMV, { GOLDEN_FRAME, ALTREF_FRAME } },
+  { NEW_NEWMV, { GOLDEN_FRAME, ALTREF_FRAME } },
+  { GLOBAL_GLOBALMV, { GOLDEN_FRAME, ALTREF_FRAME } },
+
+  { NEW_NEARMV, { LAST_FRAME, BWDREF_FRAME } },
+  { NEAR_NEWMV, { LAST_FRAME, BWDREF_FRAME } },
+  { NEW_NEWMV, { LAST_FRAME, BWDREF_FRAME } },
+  { GLOBAL_GLOBALMV, { LAST_FRAME, BWDREF_FRAME } },
+
+  { NEW_NEARMV, { LAST2_FRAME, BWDREF_FRAME } },
+  { NEAR_NEWMV, { LAST2_FRAME, BWDREF_FRAME } },
+  { NEW_NEWMV, { LAST2_FRAME, BWDREF_FRAME } },
+  { GLOBAL_GLOBALMV, { LAST2_FRAME, BWDREF_FRAME } },
+
+  { NEW_NEARMV, { LAST3_FRAME, BWDREF_FRAME } },
+  { NEAR_NEWMV, { LAST3_FRAME, BWDREF_FRAME } },
+  { NEW_NEWMV, { LAST3_FRAME, BWDREF_FRAME } },
+  { GLOBAL_GLOBALMV, { LAST3_FRAME, BWDREF_FRAME } },
+
+  { NEW_NEARMV, { GOLDEN_FRAME, BWDREF_FRAME } },
+  { NEAR_NEWMV, { GOLDEN_FRAME, BWDREF_FRAME } },
+  { NEW_NEWMV, { GOLDEN_FRAME, BWDREF_FRAME } },
+  { GLOBAL_GLOBALMV, { GOLDEN_FRAME, BWDREF_FRAME } },
+
+  { NEW_NEARMV, { LAST_FRAME, ALTREF2_FRAME } },
+  { NEAR_NEWMV, { LAST_FRAME, ALTREF2_FRAME } },
+  { NEW_NEWMV, { LAST_FRAME, ALTREF2_FRAME } },
+  { GLOBAL_GLOBALMV, { LAST_FRAME, ALTREF2_FRAME } },
+
+  { NEW_NEARMV, { LAST2_FRAME, ALTREF2_FRAME } },
+  { NEAR_NEWMV, { LAST2_FRAME, ALTREF2_FRAME } },
+  { NEW_NEWMV, { LAST2_FRAME, ALTREF2_FRAME } },
+  { GLOBAL_GLOBALMV, { LAST2_FRAME, ALTREF2_FRAME } },
+
+  { NEW_NEARMV, { LAST3_FRAME, ALTREF2_FRAME } },
+  { NEAR_NEWMV, { LAST3_FRAME, ALTREF2_FRAME } },
+  { NEW_NEWMV, { LAST3_FRAME, ALTREF2_FRAME } },
+  { GLOBAL_GLOBALMV, { LAST3_FRAME, ALTREF2_FRAME } },
+
+  { NEW_NEARMV, { GOLDEN_FRAME, ALTREF2_FRAME } },
+  { NEAR_NEWMV, { GOLDEN_FRAME, ALTREF2_FRAME } },
+  { NEW_NEWMV, { GOLDEN_FRAME, ALTREF2_FRAME } },
+  { GLOBAL_GLOBALMV, { GOLDEN_FRAME, ALTREF2_FRAME } },
+
+  { NEW_NEARMV, { LAST_FRAME, LAST2_FRAME } },
+  { NEAR_NEWMV, { LAST_FRAME, LAST2_FRAME } },
+  { NEW_NEWMV, { LAST_FRAME, LAST2_FRAME } },
+  { GLOBAL_GLOBALMV, { LAST_FRAME, LAST2_FRAME } },
+
+  { NEW_NEARMV, { LAST_FRAME, LAST3_FRAME } },
+  { NEAR_NEWMV, { LAST_FRAME, LAST3_FRAME } },
+  { NEW_NEWMV, { LAST_FRAME, LAST3_FRAME } },
+  { GLOBAL_GLOBALMV, { LAST_FRAME, LAST3_FRAME } },
+
+  { NEW_NEARMV, { LAST_FRAME, GOLDEN_FRAME } },
+  { NEAR_NEWMV, { LAST_FRAME, GOLDEN_FRAME } },
+  { NEW_NEWMV, { LAST_FRAME, GOLDEN_FRAME } },
+  { GLOBAL_GLOBALMV, { LAST_FRAME, GOLDEN_FRAME } },
+
+  { NEW_NEARMV, { BWDREF_FRAME, ALTREF_FRAME } },
+  { NEAR_NEWMV, { BWDREF_FRAME, ALTREF_FRAME } },
+  { NEW_NEWMV, { BWDREF_FRAME, ALTREF_FRAME } },
+  { GLOBAL_GLOBALMV, { BWDREF_FRAME, ALTREF_FRAME } },
+
+  // intra modes
+  { DC_PRED, { INTRA_FRAME, NONE_FRAME } },
+  { PAETH_PRED, { INTRA_FRAME, NONE_FRAME } },
+  { SMOOTH_PRED, { INTRA_FRAME, NONE_FRAME } },
+  { SMOOTH_V_PRED, { INTRA_FRAME, NONE_FRAME } },
+  { SMOOTH_H_PRED, { INTRA_FRAME, NONE_FRAME } },
+  { H_PRED, { INTRA_FRAME, NONE_FRAME } },
+  { V_PRED, { INTRA_FRAME, NONE_FRAME } },
+  { D135_PRED, { INTRA_FRAME, NONE_FRAME } },
+  { D203_PRED, { INTRA_FRAME, NONE_FRAME } },
+  { D157_PRED, { INTRA_FRAME, NONE_FRAME } },
+  { D67_PRED, { INTRA_FRAME, NONE_FRAME } },
+  { D113_PRED, { INTRA_FRAME, NONE_FRAME } },
+  { D45_PRED, { INTRA_FRAME, NONE_FRAME } },
+};
+#else
 static const MODE_DEFINITION av1_mode_defs[MAX_MODES] = {
   { NEARESTMV, { LAST_FRAME, NONE_FRAME } },
   { NEARESTMV, { LAST2_FRAME, NONE_FRAME } },
@@ -229,6 +370,7 @@
   { D113_PRED, { INTRA_FRAME, NONE_FRAME } },
   { D45_PRED, { INTRA_FRAME, NONE_FRAME } },
 };
+#endif  // CONFIG_NEW_INTER_MODES
 
 static AOM_INLINE void restore_dst_buf(MACROBLOCKD *xd, const BUFFER_SET dst,
                                        const int num_planes) {
diff --git a/av1/encoder/speed_features.h b/av1/encoder/speed_features.h
index 4e81890..186de45 100644
--- a/av1/encoder/speed_features.h
+++ b/av1/encoder/speed_features.h
@@ -77,6 +77,16 @@
       (1 << DC_PRED) | (1 << PAETH_PRED) | (1 << V_PRED) | (1 << H_PRED)
 };
 
+#if CONFIG_NEW_INTER_MODES
+enum {
+  INTER_ALL = (1 << NEARMV) | (1 << GLOBALMV) | (1 << NEWMV) |
+              (1 << NEAR_NEARMV) | (1 << NEW_NEWMV) | (1 << NEAR_NEWMV) |
+              (1 << NEW_NEARMV) | (1 << GLOBAL_GLOBALMV),
+  INTER_NEAREST_NEAR_ZERO = (1 << NEARMV) | (1 << GLOBALMV) |
+                            (1 << GLOBAL_GLOBALMV) | (1 << NEW_NEARMV) |
+                            (1 << NEAR_NEWMV) | (1 << NEAR_NEARMV),
+};
+#else
 enum {
   INTER_ALL = (1 << NEARESTMV) | (1 << NEARMV) | (1 << GLOBALMV) |
               (1 << NEWMV) | (1 << NEAREST_NEARESTMV) | (1 << NEAR_NEARMV) |
@@ -88,6 +98,7 @@
                             (1 << NEW_NEARMV) | (1 << NEAR_NEWMV) |
                             (1 << NEAR_NEARMV),
 };
+#endif  // CONFIG_NEW_INTER_MODES
 
 enum {
   DISABLE_ALL_INTER_SPLIT = (1 << THR_COMP_GA) | (1 << THR_COMP_LA) |
diff --git a/build/cmake/aom_config_defaults.cmake b/build/cmake/aom_config_defaults.cmake
index 72ec111..5ec2111 100644
--- a/build/cmake/aom_config_defaults.cmake
+++ b/build/cmake/aom_config_defaults.cmake
@@ -154,6 +154,8 @@
   "AV2 experiment flag to enable offset based refinement of intra prediction.")
 set_aom_config_var(CONFIG_IST 1 NUMBER
                    "AV2 experiment flag to enable intra secondary transform.")
+set_aom_config_var(CONFIG_NEW_INTER_MODES 0 NUMBER
+                   "AV2 inter mode consolidation experiment flag")
 
 #
 # Variables in this section control optional features of the build system.
diff --git a/examples/inspect.c b/examples/inspect.c
index 304bbc8..93cca60 100644
--- a/examples/inspect.c
+++ b/examples/inspect.c
@@ -211,7 +211,31 @@
                                       ENUM(SMOOTH_SMOOTH), ENUM(SMOOTH_SHARP),
                                       ENUM(SHARP_REG),     ENUM(SHARP_SMOOTH),
                                       ENUM(SHARP_SHARP),   LAST_ENUM };
-
+#if CONFIG_NEW_INTER_MODES
+const map_entry prediction_mode_map[] = { ENUM(DC_PRED),
+                                          ENUM(V_PRED),
+                                          ENUM(H_PRED),
+                                          ENUM(D45_PRED),
+                                          ENUM(D135_PRED),
+                                          ENUM(D113_PRED),
+                                          ENUM(D157_PRED),
+                                          ENUM(D203_PRED),
+                                          ENUM(D67_PRED),
+                                          ENUM(SMOOTH_PRED),
+                                          ENUM(SMOOTH_V_PRED),
+                                          ENUM(SMOOTH_H_PRED),
+                                          ENUM(PAETH_PRED),
+                                          ENUM(NEARMV),
+                                          ENUM(GLOBALMV),
+                                          ENUM(NEWMV),
+                                          ENUM(NEAR_NEARMV),
+                                          ENUM(NEAR_NEWMV),
+                                          ENUM(NEW_NEARMV),
+                                          ENUM(GLOBAL_GLOBALMV),
+                                          ENUM(NEW_NEWMV),
+                                          ENUM(INTRA_INVALID),
+                                          LAST_ENUM };
+#else
 const map_entry prediction_mode_map[] = {
   ENUM(DC_PRED),     ENUM(V_PRED),        ENUM(H_PRED),
   ENUM(D45_PRED),    ENUM(D135_PRED),     ENUM(D113_PRED),
@@ -223,6 +247,7 @@
   ENUM(NEAR_NEWMV),  ENUM(NEW_NEARMV),    ENUM(GLOBAL_GLOBALMV),
   ENUM(NEW_NEWMV),   ENUM(INTRA_INVALID), LAST_ENUM
 };
+#endif  // CONFIG_NEW_INTER_MODES
 
 const map_entry motion_mode_map[] = { ENUM(SIMPLE_TRANSLATION),
                                       ENUM(OBMC_CAUSAL),    // 2-sided OBMC
diff --git a/tools/aom_entropy_optimizer.c b/tools/aom_entropy_optimizer.c
index cad59e5..24fae9e 100644
--- a/tools/aom_entropy_optimizer.c
+++ b/tools/aom_entropy_optimizer.c
@@ -389,6 +389,19 @@
                      "static const aom_cdf_prob "
                      "default_zeromv_cdf[GLOBALMV_MODE_CONTEXTS][CDF_SIZE(2)]");
 
+#if CONFIG_NEW_INTER_MODES
+  cts_each_dim[0] = DRL_MODE_CONTEXTS;
+  cts_each_dim[1] = 2;
+  optimize_cdf_table(&fc.drl_mode[0][0][0], probsfile, 2, cts_each_dim,
+                     "static const aom_cdf_prob "
+                     "default_drl0_cdf[DRL_MODE_CONTEXTS][CDF_SIZE(2)]");
+  optimize_cdf_table(&fc.drl_mode[1][0][0], probsfile, 2, cts_each_dim,
+                     "static const aom_cdf_prob "
+                     "default_drl1_cdf[DRL_MODE_CONTEXTS][CDF_SIZE(2)]");
+  optimize_cdf_table(&fc.drl_mode[2][0][0], probsfile, 2, cts_each_dim,
+                     "static const aom_cdf_prob "
+                     "default_drl2_cdf[DRL_MODE_CONTEXTS][CDF_SIZE(2)]");
+#else
   cts_each_dim[0] = REFMV_MODE_CONTEXTS;
   cts_each_dim[1] = 2;
   optimize_cdf_table(&fc.refmv_mode[0][0], probsfile, 2, cts_each_dim,
@@ -400,6 +413,7 @@
   optimize_cdf_table(&fc.drl_mode[0][0], probsfile, 2, cts_each_dim,
                      "static const aom_cdf_prob "
                      "default_drl_cdf[DRL_MODE_CONTEXTS][CDF_SIZE(2)]");
+#endif  // CONFIG_NEW_INTER_MODES
 
   /* ext_inter experiment */
   /* New compound mode */