diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp
index c8414003..6f5c47e5 100644
--- a/source/Lib/CommonLib/InterPrediction.cpp
+++ b/source/Lib/CommonLib/InterPrediction.cpp
@@ -1,4 +1,4 @@
-﻿/* The copyright in this software is being made available under the BSD
+/* The copyright in this software is being made available under the BSD
  * License, included below. This software may be subject to other third party
  * and contributor rights, including patent rights, and no such rights are
  * granted under this license.
@@ -15355,6 +15355,14 @@ void InterPrediction::deriveTMMv(PredictionUnit& pu)
       RefPicList eTargetPicList = (minCostUni[0] <= minCostUni[1]) ? REF_PIC_LIST_1 : REF_PIC_LIST_0;
       MvField    mvfBetterUni(pu.mv[1 - eTargetPicList], pu.refIdx[1 - eTargetPicList]);
       Distortion biCost = deriveTMMv(pu, true, std::numeric_limits<Distortion>::max(), eTargetPicList, pu.refIdx[eTargetPicList], 0, pu.mv[eTargetPicList], &mvfBetterUni);
+#if ITERATIVE_TM_SEARCH
+      if ((biCost > (minCostUni[1 - eTargetPicList] + (minCostUni[1 - eTargetPicList] >> 3))) || !pu.cs->slice->getCheckLDC())
+      {
+        eTargetPicList = (minCostUni[0] <= minCostUni[1]) ? REF_PIC_LIST_0 : REF_PIC_LIST_1;
+        MvField mvfBetterUni2nd(pu.mv[1 - eTargetPicList], pu.refIdx[1 - eTargetPicList]);
+        biCost = deriveTMMv(pu, true, std::numeric_limits<Distortion>::max(), eTargetPicList, pu.refIdx[eTargetPicList], TM_MAX_NUM_OF_ITERATIONS, pu.mv[eTargetPicList], &mvfBetterUni2nd);
+      }
+#endif
       *tmCost = biCost;
     }
     else
@@ -15365,7 +15373,9 @@ void InterPrediction::deriveTMMv(PredictionUnit& pu)
 
   if (pu.cu->slice->isInterB() && pu.interDir == 3
 #if MULTI_PASS_DMVR
+#if !TM_SEARCH_BI_ALSO_FOR_DMVR
     && !PU::checkBDMVRCondition(pu)
+#endif
 #endif
     )
   {
@@ -15378,6 +15388,15 @@ void InterPrediction::deriveTMMv(PredictionUnit& pu)
     MvField    mvfBetterUni(pu.mv[1 - eTargetPicList], pu.refIdx[1 - eTargetPicList]);
     Distortion minCostBi = deriveTMMv(pu, true, std::numeric_limits<Distortion>::max(), eTargetPicList, pu.refIdx[eTargetPicList], TM_MAX_NUM_OF_ITERATIONS, pu.mv[eTargetPicList], &mvfBetterUni);
 
+#if ITERATIVE_TM_SEARCH
+    if ((minCostBi > (minCostUni[1 - eTargetPicList] + (minCostUni[1 - eTargetPicList] >> 3))) || !pu.cs->slice->getCheckLDC())
+    {
+      eTargetPicList = (minCostUni[0] <= minCostUni[1]) ? REF_PIC_LIST_0 : REF_PIC_LIST_1;
+      MvField mvfBetterUni2nd(pu.mv[1 - eTargetPicList], pu.refIdx[1 - eTargetPicList]);
+      minCostBi = deriveTMMv(pu, true, std::numeric_limits<Distortion>::max(), eTargetPicList, pu.refIdx[eTargetPicList], TM_MAX_NUM_OF_ITERATIONS, pu.mv[eTargetPicList], &mvfBetterUni2nd);
+    }
+#endif
+
     if (minCostBi > (minCostUni[1 - eTargetPicList] + (minCostUni[1 - eTargetPicList] >> 3)))
     {
       pu.interDir = 1 + (1 - eTargetPicList);
@@ -16126,6 +16145,9 @@ void TplMatchingCtrl::xRefineMvSearch(int maxSearchRounds, int searchStepShift)
   // Search pattern configuration
   static const Mv patternCross  [4] = { Mv(0, 1), Mv(1, 0), Mv(0, -1), Mv(-1, 0) };
   static const Mv patternDiamond[8] = { Mv(0, 2), Mv(1, 1), Mv(2, 0), Mv(1, -1), Mv(0, -2), Mv(-1, -1), Mv(-2, 0), Mv(-1, 1) };
+#if TM_SEARCH_LARGER_DIAMOND
+  static const Mv patternDiamond16[16] = { Mv(0, 2), Mv(1, 1), Mv(2, 0), Mv(1, -1), Mv(0, -2), Mv(-1, -1), Mv(-2, 0), Mv(-1, 1), Mv(0, 4), Mv(3, 3), Mv(4, 0), Mv(3, -3), Mv(0, -4), Mv(-3, -3), Mv(-4, 0), Mv(-3, 3) };
+#endif
 
   int       directStart = 0, directEnd = 0, directRounding = 0, directMask = 0;
   const Mv *pSearchOffset = nullptr;
@@ -16150,10 +16172,27 @@ void TplMatchingCtrl::xRefineMvSearch(int maxSearchRounds, int searchStepShift)
     directRounding = 8;
     directMask     = 0x07;
     pSearchOffset  = patternDiamond;
+#if TM_SEARCH_LARGER_DIAMOND
+    if (!CU::isIBC(m_cu))
+    {
+      directEnd      = 15;
+      directRounding = 16;
+      directMask     = 0x0F;
+      pSearchOffset  = patternDiamond16;
+    }
+#endif
 #if MULTI_PASS_DMVR
     memset(m_tmCostArrayDiamond, -1, sizeof(m_tmCostArrayDiamond));
     costArray      = m_tmCostArrayDiamond;
     costArray[8]   = m_minCost;
+#if TM_SEARCH_LARGER_DIAMOND
+    if (!CU::isIBC(m_cu))
+    {
+      memset(m_tmCostArrayDiamond16, -1, sizeof(m_tmCostArrayDiamond16));
+      costArray      = m_tmCostArrayDiamond16;
+      costArray[17]   = m_minCost;
+    }
+#endif
 #endif
   }
   else
@@ -16177,6 +16216,9 @@ void TplMatchingCtrl::xRefineMvSearch(int maxSearchRounds, int searchStepShift)
 #endif
 #endif
 
+#if TM_SEARCH_LARGER_DIAMOND
+    bool earlyStop = false;
+#endif
   // Iterative search
   for (int uiRound = 0; uiRound < maxSearchRounds; uiRound++)
   {
@@ -16185,7 +16227,19 @@ void TplMatchingCtrl::xRefineMvSearch(int maxSearchRounds, int searchStepShift)
 #if JVET_X0056_DMVD_EARLY_TERMINATION
     Distortion prevMinCost = m_minCost;
 #endif
+#if TM_SEARCH_LARGER_DIAMOND
+    if (earlyStop)
+    {
+      break;
+    }
+    int diamondLoopNum = !CU::isIBC(m_cu) && (!m_cu.slice->getCheckLDC() || (m_cu.slice->getCheckLDC() && m_pu.lwidth()*m_pu.lheight() >= 256)) && searchPattern == TMSEARCH_DIAMOND && uiRound > 0 ? 2 : 1;
+    for (int diamondIdx = 0; diamondIdx < diamondLoopNum; diamondIdx++)
+    {
+      int idxShift = ((uiRound == 0 || CU::isIBC(m_cu)) ? 0 : (diamondIdx - (directStart < 8 ? 0 : 1))) << 3;
+      for (int nIdx = directStart + idxShift; nIdx <= directEnd + idxShift; nIdx++)
+#else
     for (int nIdx = directStart; nIdx <= directEnd; nIdx++)
+#endif
     {
       int nDirect = (nIdx + directRounding) & directMask;
 
@@ -16234,11 +16288,17 @@ void TplMatchingCtrl::xRefineMvSearch(int maxSearchRounds, int searchStepShift)
 
     if (directBest == -1)
     {
+#if TM_SEARCH_LARGER_DIAMOND
+      earlyStop = true;
+#endif
       break;
     }
 #if JVET_X0056_DMVD_EARLY_TERMINATION
     if (uiRound > 0 && prevMinCost < m_minCost + m_earlyTerminateTh)
     {
+#if TM_SEARCH_LARGER_DIAMOND
+      earlyStop = true;
+#endif
       break;
     }
 #endif
@@ -16252,6 +16312,9 @@ void TplMatchingCtrl::xRefineMvSearch(int maxSearchRounds, int searchStepShift)
     {
       xNextTmCostAarray<searchPattern>(directBest);
     }
+#endif
+#if TM_SEARCH_LARGER_DIAMOND
+    }
 #endif
   }
 }
diff --git a/source/Lib/CommonLib/InterPrediction.h b/source/Lib/CommonLib/InterPrediction.h
index f847141b..d145e904 100644
--- a/source/Lib/CommonLib/InterPrediction.h
+++ b/source/Lib/CommonLib/InterPrediction.h
@@ -1278,6 +1278,9 @@ public:
 #endif
 #if MULTI_PASS_DMVR
   Distortion m_tmCostArrayDiamond[9];
+#if TM_SEARCH_LARGER_DIAMOND
+  Distortion m_tmCostArrayDiamond16[17];
+#endif
   Distortion m_tmCostArrayCross[5];
 #endif
 
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index d2274754..79dd0862 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -52,6 +52,21 @@
 
 
 
+#define TEST_3_3_a                                        1
+#define TEST_3_3_b                                        0
+#define TEST_3_3_c                                        0
+#define TEST_3_3_d                                        0
+#define TEST_3_3_e                                        0
+
+#if TEST_3_3_a || TEST_3_3_d || TEST_3_3_e
+#define ITERATIVE_TM_SEARCH                               1
+#endif
+#if TEST_3_3_b || TEST_3_3_e
+#define TM_SEARCH_LARGER_DIAMOND                          1
+#endif
+#if TEST_3_3_c || TEST_3_3_d || TEST_3_3_e
+#define TM_SEARCH_BI_ALSO_FOR_DMVR                        1
+#endif
 
 #define BASE_ENCODER                                      1
 #define BASE_NORMATIVE                                    1
