diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index 88235d70b7016bc4cff0a0b3c9e2ce32850465fc..5b7ec86f31eb47390807394d5329cdce29e0fa3b 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -894,6 +894,9 @@ void EncApp::xInitLibCfg()
 #if JVET_AD0082_TMRL_CONFIG
   m_cEncLib.setUseTmrl                                           ( m_tmrl );
 #endif
+#if JVET_AD0085_MPM_SORTING
+  m_cEncLib.setUseMpmSorting                                     ( m_mpmSorting );
+#endif
 #if JVET_AC0147_CCCM_NO_SUBSAMPLING
   m_cEncLib.setUseCccm                                           ( m_cccm );
 #endif
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index 039e84a72ce36d703c53e661a154df099e3a7692..0c18ef6a20716b6b56dace01a0f0ce2bb0d2145c 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -1117,6 +1117,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
 #if JVET_AD0082_TMRL_CONFIG
   ("TMRL",                                            m_tmrl,                                            true,  "Enable template based multiple reference line intra prediction\n")
 #endif
+#if JVET_AD0085_MPM_SORTING
+  ( "MPMSorting",                                     m_mpmSorting,                                      true,  "Enable template-based intra MPM list construction\n" )
+#endif
 #if JVET_AC0147_CCCM_NO_SUBSAMPLING
   ( "CCCM",                                           m_cccm,                                               2,  "CCCM mode (0:off, 1:on, 2:on subsampling and no subsampling)  [default: 2]")
 #endif
@@ -5418,6 +5421,9 @@ void EncAppCfg::xPrintParameter()
 #if JVET_AD0082_TMRL_CONFIG
   msg(VERBOSE, "TMRL:%d ", m_tmrl);
 #endif
+#if JVET_AD0085_MPM_SORTING
+  msg(VERBOSE, "MPMSorting:%d ", m_mpmSorting);
+#endif
 #if JVET_AC0147_CCCM_NO_SUBSAMPLING
   msg(VERBOSE, "CCCM:%d ", m_cccm);
 #endif
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index 88bab28bee4b83642fef136aa1304a35271964c2..32ab826e4633d0749a5b650d72fae5fc48af660f 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -472,6 +472,9 @@ protected:
 #if JVET_AD0082_TMRL_CONFIG
   bool      m_tmrl;
 #endif
+#if JVET_AD0085_MPM_SORTING
+  bool      m_mpmSorting;
+#endif
 #if JVET_AC0147_CCCM_NO_SUBSAMPLING
   int       m_cccm;
 #endif
diff --git a/source/Lib/CommonLib/Contexts.cpp b/source/Lib/CommonLib/Contexts.cpp
index e7da6c891899a65ee78ac0b11273f90b263f7533..a2467e720fb1dc21903591d02c8e87c6d20f20e0 100644
--- a/source/Lib/CommonLib/Contexts.cpp
+++ b/source/Lib/CommonLib/Contexts.cpp
@@ -1400,6 +1400,23 @@ const CtxSet ContextSetCfg::IntraLumaMPMIdx = ContextSetCfg::addCtxSet
   { 121, 126, 119, },
   { 119, 109, 121, },
   });
+
+#if JVET_AD0085_MPM_SORTING
+const CtxSet ContextSetCfg::IntraLumaSecondMpmIdx = ContextSetCfg::addCtxSet
+({
+  { CNU, CNU, CNU, CNU, CNU },
+  { CNU, CNU, CNU, CNU, CNU },
+  { CNU, CNU, CNU, CNU, CNU },
+  { DWS, DWS, DWS, DWS, DWS },
+  { DWS, DWS, DWS, DWS, DWS },
+  { DWS, DWS, DWS, DWS, DWS },
+  { DWE, DWE, DWE, DWE, DWE },
+  { DWE, DWE, DWE, DWE, DWE },
+  { DWE, DWE, DWE, DWE, DWE },
+  { 119, 119, 119, 119, 119 },
+  { 119, 119, 119, 119, 119 },
+  });
+#endif
 #endif
 
 const CtxSet ContextSetCfg::IntraLumaPlanarFlag = ContextSetCfg::addCtxSet
@@ -3803,6 +3820,17 @@ const CtxSet ContextSetCfg::IntraLumaMPMIdx = ContextSetCfg::addCtxSet
 	{ 4,  1,  6 },
 	{ 2,  2,  6 }
 });
+#if JVET_AD0085_MPM_SORTING
+const CtxSet ContextSetCfg::IntraLumaSecondMpmIdx = ContextSetCfg::addCtxSet
+({
+  { CNU, CNU, CNU, CNU, CNU },
+  { CNU, CNU, CNU, CNU, CNU },
+  { CNU, CNU, CNU, CNU, CNU },
+  { DWS, DWS, DWS, DWS, DWS },
+  { DWS, DWS, DWS, DWS, DWS },
+  { DWS, DWS, DWS, DWS, DWS },
+  });
+#endif
 #endif
 
 const CtxSet ContextSetCfg::CclmModeFlag = ContextSetCfg::addCtxSet
@@ -5350,6 +5378,15 @@ const CtxSet ContextSetCfg::IntraLumaMPMIdx = ContextSetCfg::addCtxSet
 	{ 20, 44, 35 },
 	{ 2,  2,  6 }
   });
+#if JVET_AD0085_MPM_SORTING
+const CtxSet ContextSetCfg::IntraLumaSecondMpmIdx = ContextSetCfg::addCtxSet
+({
+  { CNU, CNU, CNU, CNU, CNU },
+  { CNU, CNU, CNU, CNU, CNU },
+  { CNU, CNU, CNU, CNU, CNU },
+  { DWS, DWS, DWS, DWS, DWS },
+  });
+#endif
 #endif
 
 const CtxSet ContextSetCfg::CclmModeFlag = ContextSetCfg::addCtxSet
diff --git a/source/Lib/CommonLib/Contexts.h b/source/Lib/CommonLib/Contexts.h
index 2f32394e4db1a7831639c20d8ce23183429f1f8c..ddeebcfa00b833b310df6dda3e245345f6ca389e 100644
--- a/source/Lib/CommonLib/Contexts.h
+++ b/source/Lib/CommonLib/Contexts.h
@@ -356,6 +356,9 @@ public:
   static const CtxSet   IntraLumaMpmFlag;
 #if SECONDARY_MPM
   static const CtxSet   IntraLumaSecondMpmFlag;
+#if JVET_AD0085_MPM_SORTING
+  static const CtxSet   IntraLumaSecondMpmIdx;
+#endif
 #endif
   static const CtxSet   IntraLumaPlanarFlag;
 #if SECONDARY_MPM
diff --git a/source/Lib/CommonLib/IntraPrediction.cpp b/source/Lib/CommonLib/IntraPrediction.cpp
index 354697cebc06773a61b78f8d6f2c8b3b7dc07ddd..0388bc223c6dfe1ec778ff2106495baeb31af3fe 100644
--- a/source/Lib/CommonLib/IntraPrediction.cpp
+++ b/source/Lib/CommonLib/IntraPrediction.cpp
@@ -1174,8 +1174,18 @@ void IntraPrediction::predIntraAng( const ComponentID compId, PelBuf &piPred, co
 
   CHECK(PU::isMIP(pu, toChannelType(compId)), "We should not get here for MIP.");
   const uint32_t       uiDirMode    = isLuma( compId ) && pu.cu->bdpcmMode ? BDPCM_IDX : !isLuma(compId) && pu.cu->bdpcmModeChroma ? BDPCM_IDX : PU::getFinalIntraMode(pu, channelType);
+#if JVET_AD0085_TMRL_EXTENSION
+  bool bExtIntraDir = false;
+#if JVET_W0123_TIMD_FUSION
+  bExtIntraDir |= (pu.cu->timd && isLuma(compId));
+#endif
+#if JVET_AD0085_TMRL_EXTENSION
+  bExtIntraDir |= (pu.cu->tmrlFlag && isLuma(compId));
+#endif
+#else
 #if JVET_W0123_TIMD_FUSION
   bool bExtIntraDir = pu.cu->timd && isLuma( compId );
+#endif
 #endif
 
   CHECK( floorLog2(iWidth) < 2 && pu.cs->pcv->noChroma2x2, "Size not allowed" );
@@ -2546,8 +2556,18 @@ void IntraPrediction::initPredIntraParams(const PredictionUnit & pu, const CompA
 {
   const ComponentID compId = area.compID;
   const ChannelType chType = toChannelType(compId);
+#if JVET_AD0085_TMRL_EXTENSION
+  bool bExtIntraDir = false;
+#if JVET_W0123_TIMD_FUSION
+  bExtIntraDir |= (pu.cu->timd && isLuma(chType));
+#endif
+#if JVET_AD0085_TMRL_EXTENSION
+  bExtIntraDir |= (pu.cu->tmrlFlag && isLuma(chType));
+#endif
+#else
 #if JVET_W0123_TIMD_FUSION
   bool bExtIntraDir = pu.cu->timd && isLuma( chType );
+#endif
 #endif
 
   const bool        useISP = NOT_INTRA_SUBPARTITIONS != pu.cu->ispMode && isLuma( chType );
@@ -2562,6 +2582,16 @@ void IntraPrediction::initPredIntraParams(const PredictionUnit & pu, const CompA
 #endif
 #if JVET_W0123_TIMD_FUSION
 #if JVET_AC0094_REF_SAMPLES_OPT
+#if JVET_AD0085_TMRL_EXTENSION
+  bool checkWideAngle = !bExtIntraDir ? true : (pu.cu->timdMode != INVALID_TIMD_IDX ? pu.cu->timdModeCheckWA : pu.cu->timdModeSecondaryCheckWA);
+
+  int predMode = checkWideAngle ? (bExtIntraDir ? getWideAngleExt(blockSize.width, blockSize.height, dirMode) : getModifiedWideAngle(blockSize.width, blockSize.height, dirMode))
+    : (bExtIntraDir ? getTimdWideAngleExt(blockSize.width, blockSize.height, dirMode) : getTimdWideAngle(blockSize.width, blockSize.height, dirMode));
+  if (pu.cu->tmrlFlag && isLuma(chType))
+  {
+    predMode = getWideAngleExt(blockSize.width, blockSize.height, dirMode);
+  }
+#else
   if (bExtIntraDir)
   {
     CHECK(pu.cu->timdMode != dirMode && pu.cu->timdModeSecondary != dirMode, "Unexpected dirMode");
@@ -2570,6 +2600,7 @@ void IntraPrediction::initPredIntraParams(const PredictionUnit & pu, const CompA
   const int predMode = checkWideAngle ? (bExtIntraDir ? getWideAngleExt(blockSize.width, blockSize.height, dirMode) : getModifiedWideAngle(blockSize.width, blockSize.height, dirMode))
                          : (bExtIntraDir ? getTimdWideAngleExt(blockSize.width, blockSize.height, dirMode) : getTimdWideAngle(blockSize.width, blockSize.height, dirMode));
   CHECK(!checkWideAngle && dirMode <= DC_IDX, "Unexpected mode");
+#endif
 #else
   const int     predMode = bExtIntraDir ? getWideAngleExt( blockSize.width, blockSize.height, dirMode ) : getModifiedWideAngle( blockSize.width, blockSize.height, dirMode );
 #endif
@@ -5599,6 +5630,119 @@ void IntraPrediction::deriveSgpmModeOrdered(const CPelBuf &recoBuf, const CompAr
 }
 #endif
 
+#if JVET_AD0085_MPM_SORTING
+void IntraPrediction::deriveMPMSorted(const PredictionUnit& pu, uint8_t* mpm, int& sortedSize, int iStartIdx)
+{
+  SizeType uiWidth = pu.lwidth();
+  SizeType uiHeight = pu.lheight();
+  const CompArea area = pu.Y();
+  int channelBitDepth = pu.cu->slice->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA);
+
+  static Pel predLuma[(MAX_CU_SIZE + DIMD_MAX_TEMP_SIZE) * (MAX_CU_SIZE + DIMD_MAX_TEMP_SIZE)];
+  memset(predLuma, 0, (MAX_CU_SIZE + DIMD_MAX_TEMP_SIZE) * (MAX_CU_SIZE + DIMD_MAX_TEMP_SIZE) * sizeof(Pel));
+  Pel* piPred = predLuma;
+  uint32_t uiPredStride = MAX_CU_SIZE + DIMD_MAX_TEMP_SIZE;
+
+  int      iCurX = pu.lx();
+  int      iCurY = pu.ly();
+  int      iRefX = -1, iRefY = -1;
+  uint32_t uiRefWidth = 0, uiRefHeight = 0;
+  int      iTempWidth = 1, iTempHeight = 1;
+
+  static_vector<uint8_t, NUM_MOST_PROBABLE_MODES> uiModeList;
+  static_vector<uint64_t, NUM_MOST_PROBABLE_MODES> uiCostList;
+  int iBestN = std::min(NUM_PRIMARY_MOST_PROBABLE_MODES - 1, sortedSize);
+  if (!pu.cs->pcv->isEncoder && pu.mpmFlag && pu.ipredIdx < iBestN)
+  {
+    iBestN = pu.ipredIdx;
+  }
+
+  TEMPLATE_TYPE eTempType = CU::deriveTimdRefType(iCurX, iCurY, uiWidth, uiHeight, iTempWidth, iTempHeight, iRefX,
+    iRefY, uiRefWidth, uiRefHeight);
+
+  if (eTempType == NO_NEIGHBOR)
+  {
+    return;
+  }
+
+  const CodingStructure& cs = *pu.cs;
+  m_ipaParam.multiRefIndex = iTempWidth;
+  Pel* piOrg = cs.picture->getRecoBuf(area).buf;
+  int  iOrgStride = cs.picture->getRecoBuf(area).stride;
+  piOrg += (iRefY - iCurY) * iOrgStride + (iRefX - iCurX);
+  DistParam distParamSad[2];   // above, left
+  distParamSad[0].applyWeight = false;
+  distParamSad[0].useMR = false;
+  distParamSad[1].applyWeight = false;
+  distParamSad[1].useMR = false;
+  if (eTempType == LEFT_ABOVE_NEIGHBOR)
+  {
+    m_timdSatdCost->setTimdDistParam(distParamSad[0], piOrg + iTempWidth, piPred + iTempWidth, iOrgStride,
+      uiPredStride, channelBitDepth, COMPONENT_Y, uiWidth, iTempHeight, 0, 1, false);   // Use HAD (SATD) cost
+    m_timdSatdCost->setTimdDistParam(distParamSad[1], piOrg + iTempHeight * iOrgStride,
+      piPred + iTempHeight * uiPredStride, iOrgStride, uiPredStride, channelBitDepth,
+      COMPONENT_Y, iTempWidth, uiHeight, 0, 1, false);
+  }
+  else if (eTempType == LEFT_NEIGHBOR)
+  {
+    m_timdSatdCost->setTimdDistParam(distParamSad[1], piOrg, piPred, iOrgStride, uiPredStride, channelBitDepth,
+      COMPONENT_Y, iTempWidth, uiHeight, 0, 1, false);
+  }
+  else if (eTempType == ABOVE_NEIGHBOR)
+  {
+    m_timdSatdCost->setTimdDistParam(distParamSad[0], piOrg, piPred, iOrgStride, uiPredStride, channelBitDepth,
+      COMPONENT_Y, uiWidth, iTempHeight, 0, 1, false);
+  }
+  initTimdIntraPatternLuma(*pu.cu, area, eTempType != ABOVE_NEIGHBOR ? iTempWidth : 0,
+    eTempType != LEFT_NEIGHBOR ? iTempHeight : 0, uiRefWidth, uiRefHeight);
+
+  uint32_t uiRealW = uiRefWidth + (eTempType == LEFT_NEIGHBOR ? iTempWidth : 0);
+  uint32_t uiRealH = uiRefHeight + (eTempType == ABOVE_NEIGHBOR ? iTempHeight : 0);
+
+  for (int i = iStartIdx; i < sortedSize; i++)
+  {
+    uint64_t uiCost = 0;
+    int      iMode = mpm[i];
+    if (iMode > DC_IDX)
+    {
+      iMode = MAP67TO131(iMode);
+    }
+    initPredTimdIntraParams(pu, area, iMode);
+    predTimdIntraAng(COMPONENT_Y, pu, iMode, piPred, uiPredStride, uiRealW, uiRealH, eTempType,
+      (eTempType == ABOVE_NEIGHBOR) ? 0 : iTempWidth,
+      (eTempType == LEFT_NEIGHBOR) ? 0 : iTempHeight);
+    if (eTempType == LEFT_ABOVE_NEIGHBOR)
+    {
+      uiCost += distParamSad[0].distFunc(distParamSad[0]);
+      uiCost += distParamSad[1].distFunc(distParamSad[1]);
+    }
+    else if (eTempType == LEFT_NEIGHBOR)
+    {
+      uiCost = distParamSad[1].distFunc(distParamSad[1]);
+    }
+    else if (eTempType == ABOVE_NEIGHBOR)
+    {
+      uiCost += distParamSad[0].distFunc(distParamSad[0]);
+    }
+    else
+    {
+      assert(0);
+    }
+
+    if (uiCostList.size() < iBestN || (uiCostList.size() >= iBestN && uiCost < uiCostList.back()))
+    {
+      updateCandList(mpm[i], uiCost, uiModeList, uiCostList, iBestN);
+    }
+  }
+
+  sortedSize = int(uiModeList.size()) + iStartIdx;
+  for (int i = 0; i < uiModeList.size(); i++)
+  {
+    mpm[i + iStartIdx] = uiModeList[i];
+  }
+}
+#endif
+
 #if JVET_AB0155_SGPM
 int IntraPrediction::deriveTimdMode(const CPelBuf &recoBuf, const CompArea &area, CodingUnit &cu, bool bFull, bool bHorVer)
 {
@@ -5701,7 +5845,11 @@ int IntraPrediction::deriveTimdMode(const CPelBuf &recoBuf, const CompArea &area
     if (puLeftx && CU::isIntra(*puLeftx->cu))
     {
       uiIntraDirNeighbor[modeIdx] = PU::getIntraDirLuma(*puLeftx);
-      if (!puLeftx->cu->timd)
+      if (!puLeftx->cu->timd
+#if JVET_AD0085_TMRL_EXTENSION
+        && !puLeftx->cu->tmrlFlag
+#endif
+        )
       {
         uiIntraDirNeighbor[modeIdx] = MAP67TO131(uiIntraDirNeighbor[modeIdx]);
       }
@@ -5717,7 +5865,11 @@ int IntraPrediction::deriveTimdMode(const CPelBuf &recoBuf, const CompArea &area
     if (puAbovex && CU::isIntra(*puAbovex->cu) && CU::isSameCtu(*pu.cu, *puAbovex->cu))
     {
       uiIntraDirNeighbor[modeIdx] = PU::getIntraDirLuma(*puAbovex);
-      if (!puAbovex->cu->timd)
+      if (!puAbovex->cu->timd
+#if JVET_AD0085_TMRL_EXTENSION
+        && !puAbovex->cu->tmrlFlag
+#endif
+        )
       {
         uiIntraDirNeighbor[modeIdx] = MAP67TO131(uiIntraDirNeighbor[modeIdx]);
       }
@@ -5733,7 +5885,11 @@ int IntraPrediction::deriveTimdMode(const CPelBuf &recoBuf, const CompArea &area
     if (puLeftBottomx && CU::isIntra(*puLeftBottomx->cu))
     {
       uiIntraDirNeighbor[modeIdx] = PU::getIntraDirLuma(*puLeftBottomx);
-      if (!puLeftBottomx->cu->timd)
+      if (!puLeftBottomx->cu->timd
+#if JVET_AD0085_TMRL_EXTENSION
+        && !puLeftBottomx->cu->tmrlFlag
+#endif
+        )
       {
         uiIntraDirNeighbor[modeIdx] = MAP67TO131(uiIntraDirNeighbor[modeIdx]);
       }
@@ -5761,7 +5917,11 @@ int IntraPrediction::deriveTimdMode(const CPelBuf &recoBuf, const CompArea &area
     if (puAboveRightx && CU::isIntra(*puAboveRightx->cu))
     {
       uiIntraDirNeighbor[modeIdx] = PU::getIntraDirLuma(*puAboveRightx);
-      if (!puAboveRightx->cu->timd)
+      if (!puAboveRightx->cu->timd
+#if JVET_AD0085_TMRL_EXTENSION
+        && !puAboveRightx->cu->tmrlFlag
+#endif
+        )
       {
         uiIntraDirNeighbor[modeIdx] = MAP67TO131(uiIntraDirNeighbor[modeIdx]);
       }
@@ -5787,7 +5947,11 @@ int IntraPrediction::deriveTimdMode(const CPelBuf &recoBuf, const CompArea &area
     if (puAboveLeftx && CU::isIntra(*puAboveLeftx->cu))
     {
       uiIntraDirNeighbor[modeIdx] = PU::getIntraDirLuma(*puAboveLeftx);
-      if (!puAboveLeftx->cu->timd)
+      if (!puAboveLeftx->cu->timd
+#if JVET_AD0085_TMRL_EXTENSION
+        && !puAboveLeftx->cu->tmrlFlag
+#endif
+        )
       {
         uiIntraDirNeighbor[modeIdx] = MAP67TO131(uiIntraDirNeighbor[modeIdx]);
       }
@@ -13645,6 +13809,15 @@ void IntraPrediction::xPredTmrlIntraDc(const CPelBuf& pSrc, Pel* pDst, int iDstS
 
 Pel tmrlFiltering(Pel* pSrc, const int deltaFrac)
 {
+#if JVET_AD0085_TMRL_EXTENSION
+  const TFilterCoeff* const f = InterpolationFilter::getExtIntraCubicFilter(deltaFrac);
+  int val = 0;
+  for (int i = 0; i < 4; i++)
+  {
+    val += pSrc[i] * f[i];
+  }
+  val = (val + 128) >> 8;
+#else
   const TFilterCoeff IntraCubicFilter[32][4] =
   {
     {  0, 64,  0,  0 },
@@ -13687,6 +13860,7 @@ Pel tmrlFiltering(Pel* pSrc, const int deltaFrac)
     val += pSrc[i] * IntraCubicFilter[deltaFrac][i];
   }
   val = (val + 32) >> 6;
+#endif
   return Pel(val);
 }
 
@@ -13808,10 +13982,15 @@ void IntraPrediction::xPredTmrlIntraAng(const CPelBuf& pSrc, const ClpRng& clpRn
         iStartIdx = 0;
         iEndIdx = uiTemplateLeft;
       }
-
+#if JVET_AD0085_TMRL_EXTENSION
+      const int deltaInt = deltaPos >> 6;
+      const int deltaFract = deltaPos & 63;
+      if (!isIntegerSlopeExt(abs(intraPredAngle)))
+#else
       const int deltaInt = deltaPos >> 5;
       const int deltaFract = deltaPos & 31;
       if (!isIntegerSlope(abs(intraPredAngle)))
+#endif
       {
         CHECK(deltaInt + iStartIdx + lineOffset < -int(uiRefHeight), "over the prepared reference buffer.");
         for (int x = iStartIdx; x < iEndIdx; x++)
@@ -13872,6 +14051,27 @@ void IntraPrediction::initTmrlIntraParams(const PredictionUnit& pu, const CompAr
   const ChannelType chType = toChannelType(compId);
   const Size& blockSize = Size(pu.cu->blocks[compId].width, pu.cu->blocks[compId].height);
   const int      dirMode = PU::getFinalIntraMode(pu, chType);
+#if JVET_AD0085_TMRL_EXTENSION
+  const int     predMode = getWideAngleExt(blockSize.width, blockSize.height, dirMode);
+  m_ipaParam.isModeVer = predMode >= EXT_DIA_IDX;
+  m_ipaParam.multiRefIndex = pu.multiRefIdx;
+  m_ipaParam.refFilterFlag = false;
+  m_ipaParam.applyPDPC = false;
+  const int    intraPredAngleMode = (m_ipaParam.isModeVer) ? predMode - EXT_VER_IDX : -(predMode - EXT_HOR_IDX);
+  if (dirMode > DC_IDX)
+  {
+    int absAng = 0;
+    static const int extAngTable[64] = { 0, 1, 2, 3, 4, 5, 6,7, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 43, 46, 49, 52, 55, 58, 61, 64, 67, 70, 74, 78, 84, 90, 96, 102, 108, 114, 121, 128, 137, 146, 159, 172, 188, 204, 230, 256, 299, 342, 427, 512, 597, 682, 853, 1024, 1536, 2048, 3072 };
+    static const int extInvAngTable[64] = { 0, 32768, 16384, 10923, 8192, 6554, 5461, 4681, 4096, 3277, 2731, 2341, 2048, 1820, 1638, 1489, 1365, 1260, 1170, 1092, 1024, 964, 910, 862, 819, 762, 712, 669, 630, 596, 565, 537, 512, 489, 468, 443, 420, 390, 364, 341, 321, 303, 287, 271, 256, 239, 224, 206, 191, 174, 161, 142, 128, 110, 96, 77, 64, 55, 48, 38, 32, 21, 16, 11 }; // (512 * 64) / Angle
+
+    const int     absAngMode = abs(intraPredAngleMode);
+    const int     signAng = intraPredAngleMode < 0 ? -1 : 1;
+    absAng = extAngTable[absAngMode];
+
+    m_ipaParam.absInvAngle = extInvAngTable[absAngMode];
+    m_ipaParam.intraPredAngle = signAng * absAng;
+  }
+#else
   const int     predMode = getModifiedWideAngle(blockSize.width, blockSize.height, dirMode);
   m_ipaParam.isModeVer = predMode >= DIA_IDX;
   m_ipaParam.multiRefIndex = pu.multiRefIdx;
@@ -13895,6 +14095,7 @@ void IntraPrediction::initTmrlIntraParams(const PredictionUnit& pu, const CompAr
     m_ipaParam.absInvAngle = invAngTable[absAngMode];
     m_ipaParam.intraPredAngle = signAng * absAng;
   }
+#endif
 }
 
 void IntraPrediction::getTmrlSearchRange(const PredictionUnit& pu, int8_t* tmrlRefList, uint8_t* tmrlIntraList, uint8_t& sizeRef, uint8_t& sizeMode)
@@ -13912,6 +14113,16 @@ void IntraPrediction::getTmrlSearchRange(const PredictionUnit& pu, int8_t* tmrlR
     }
   }
 
+#if JVET_AD0085_TMRL_EXTENSION
+  sizeMode = TMRL_MPM_SIZE;
+  int numCand = getSpatialIpm(pu, tmrlIntraList, sizeMode
+#if JVET_AC0094_REF_SAMPLES_OPT
+                            , true
+#endif
+                            , true
+  );
+  fillMPMList(pu, tmrlIntraList, sizeMode, numCand, true);
+#else
   // intra mode candidates
   sizeMode = 0;
   const CodingStructure& cs = *pu.cs;
@@ -14141,6 +14352,7 @@ void IntraPrediction::getTmrlSearchRange(const PredictionUnit& pu, int8_t* tmrlR
       includedMode[tmrlIntraList[sizeMode++]] = true;
     }
   }
+#endif
 }
 
 void IntraPrediction::getTmrlList(CodingUnit& cu)
diff --git a/source/Lib/CommonLib/IntraPrediction.h b/source/Lib/CommonLib/IntraPrediction.h
index afb1fe206f8607793351937c83d5d9fabad7582d..79e7254e3f5ac14e0798f175bcb5756c442f5c64 100644
--- a/source/Lib/CommonLib/IntraPrediction.h
+++ b/source/Lib/CommonLib/IntraPrediction.h
@@ -562,6 +562,9 @@ public:
                              static_vector<SgpmInfo, SGPM_NUM> &candModeList,
                              static_vector<double, SGPM_NUM> &  candCostList);
 #endif
+#if JVET_AD0085_MPM_SORTING
+  void deriveMPMSorted(const PredictionUnit& pu, uint8_t* mpm, int& sortedSize, int iStartIdx);
+#endif
 #if JVET_AB0157_TMRL
   struct TmrlInfo
   {
diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h
index 4f41a1d2ae9c224bfa0548327bf9683569e37780..1c0bb5a6fd7a21482eec7cb5a7bfed62e50364ad 100644
--- a/source/Lib/CommonLib/Slice.h
+++ b/source/Lib/CommonLib/Slice.h
@@ -1761,6 +1761,9 @@ private:
 #if JVET_AD0082_TMRL_CONFIG
   bool              m_tmrl;
 #endif
+#if JVET_AD0085_MPM_SORTING
+  bool              m_mpmSorting;
+#endif
 #if JVET_AC0147_CCCM_NO_SUBSAMPLING
   int               m_cccm;
 #endif
@@ -2369,6 +2372,10 @@ void                    setCCALFEnabledFlag( bool b )
   void      setUseTmrl         (bool b)                                          { m_tmrl = b; }
   bool      getUseTmrl         ()                                      const     { return m_tmrl; }
 #endif
+#if JVET_AD0085_MPM_SORTING
+  void      setUseMpmSorting   (bool b)                                          { m_mpmSorting = b; }
+  bool      getUseMpmSorting   ()                                      const     { return m_mpmSorting; }
+#endif
 #if JVET_AC0147_CCCM_NO_SUBSAMPLING
   void      setUseCccm( int i )                                                  { m_cccm = i; }
   int       getUseCccm()                                               const     { return m_cccm; }
diff --git a/source/Lib/CommonLib/TrQuant.cpp b/source/Lib/CommonLib/TrQuant.cpp
index 3daa8e6a4f28ddac9dcc968333e1d8804b402c4b..ea9a7850dd82111146302e0b8ada8950e3d95110 100644
--- a/source/Lib/CommonLib/TrQuant.cpp
+++ b/source/Lib/CommonLib/TrQuant.cpp
@@ -544,6 +544,12 @@ void TrQuant::xInvLfnst( const TransformUnit &tu, const ComponentID compID )
     {
       intraMode = PLANAR_IDX;
     }
+#endif
+#if JVET_AD0085_TMRL_EXTENSION
+    if (tu.cu->tmrlFlag && compID == COMPONENT_Y)
+    {
+      intraMode = MAP131TO67(intraMode);
+    }
 #endif
     CHECK( intraMode >= NUM_INTRA_MODE - 1, "Invalid intra mode" );
 
@@ -811,6 +817,12 @@ void TrQuant::xFwdLfnst( const TransformUnit &tu, const ComponentID compID, cons
     {
       intraMode = PLANAR_IDX;
     }
+#endif
+#if JVET_AD0085_TMRL_EXTENSION
+    if (tu.cu->tmrlFlag && compID == COMPONENT_Y)
+    {
+      intraMode = MAP131TO67(intraMode);
+    }
 #endif
     CHECK( intraMode >= NUM_INTRA_MODE - 1, "Invalid intra mode" );
 
@@ -1236,6 +1248,12 @@ void TrQuant::getTrTypes(const TransformUnit tu, const ComponentID compID, int &
       {
         predMode = g_geoAngle2IntraAng[g_geoParams[tu.cu->sgpmSplitDir][0]];
       }
+#endif
+#if JVET_AD0085_TMRL_EXTENSION
+      if (tu.cu->tmrlFlag && compID == COMPONENT_Y)
+      {
+        predMode = MAP131TO67(predMode);
+      }
 #endif
       int ucMode;
       int nMdIdx;
@@ -2655,6 +2673,12 @@ int TrQuant::getLfnstIdx(const TransformUnit &tu, ComponentID compID)
     intraMode = PLANAR_IDX;
   }
 #endif
+#if JVET_AD0085_TMRL_EXTENSION
+  if (tu.cu->tmrlFlag && compID == COMPONENT_Y)
+  {
+    intraMode = MAP131TO67(intraMode);
+  }
+#endif
 #if JVET_AC0105_DIRECTIONAL_PLANAR
   if (compID == COMPONENT_Y && intraMode == PLANAR_IDX)
   {
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 8acdbf3cdb0940b88f63e19f1a4f2b544355cc7d..016baa238769be147c7721b40ea0fceb854bea55 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -173,11 +173,13 @@
 #define JVET_AB0157_TMRL                                  1 // JVET-AB0157: Template-based multiple reference line intra prediction
 #if JVET_AB0157_TMRL
 #define JVET_AD0082_TMRL_CONFIG                           1 // JVET-AD0082: a configuration option for TMRL
+#define JVET_AD0085_TMRL_EXTENSION                        1 // JVET-AD0085: TMRL angular extension and intra candidate list modifications
 #endif
 #define JVET_AB0157_INTRA_FUSION                          1 // JVET-AB0157: Intra prediction fusion
 #define JVET_AC0094_REF_SAMPLES_OPT                       1 // JVET-AC0094: Optimizing the use of reference samples
 #define JVET_AC0105_DIRECTIONAL_PLANAR                    1 // JVET-AC0105: Directional planar
 #define JVET_AD0184_REMOVAL_OF_DIVISION_OPERATIONS        1 // JVET-AD0184: Removal of division operations
+#define JVET_AD0085_MPM_SORTING                           1 // JVET-AD0085: Template-based intra MPM list construction
 
 //IBC
 #define JVET_Y0058_IBC_LIST_MODIFY                        1 // JVET-Y0058: Modifications of IBC merge/AMVP list construction, ARMC-TM-IBC part is included under JVET_W0090_ARMC_TM
diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp
index 6236bf6a969f27114194503ed0782b76d6c00ec0..d91f1cd157f3a92587c53e1f81655e13df192435 100644
--- a/source/Lib/CommonLib/UnitTools.cpp
+++ b/source/Lib/CommonLib/UnitTools.cpp
@@ -883,13 +883,45 @@ bool CU::isIdxModeValid(const bool &areAboveRightUnavail, const bool &areBelowLe
 #if SECONDARY_MPM
 int PU::getIntraMPMs( const PredictionUnit &pu, uint8_t* mpm, uint8_t* non_mpm
 #if JVET_AC0094_REF_SAMPLES_OPT
-                     , const bool& isForcedValid
+                    , const bool& isForcedValid
 #endif
-    , const ChannelType &channelType /*= CHANNEL_TYPE_LUMA*/)
+#if JVET_AD0085_MPM_SORTING
+                    , IntraPrediction* pIntraPred/* = nullptr*/
+#endif
+                    , const ChannelType &channelType /*= CHANNEL_TYPE_LUMA*/)
 #else
 int PU::getIntraMPMs(const PredictionUnit &pu, unsigned* mpm, const ChannelType &channelType /*= CHANNEL_TYPE_LUMA*/)
 #endif
 {
+#if JVET_AD0085_TMRL_EXTENSION && SECONDARY_MPM
+  int numCand = 0;
+  mpm[numCand++] = PLANAR_IDX;
+#if JVET_AD0085_MPM_SORTING
+  int maxCand = pIntraPred ? NUM_PRIMARY_MOST_PROBABLE_MODES + 1 : NUM_MOST_PROBABLE_MODES - 1;
+#else
+  int maxCand = NUM_MOST_PROBABLE_MODES - 1;
+#endif
+  numCand += getSpatialIpm(pu, mpm + 1, maxCand
+#if JVET_AC0094_REF_SAMPLES_OPT
+                         , isForcedValid
+#endif
+                         , false
+#if JVET_AD0085_MPM_SORTING
+                         , pIntraPred
+#endif
+  );
+
+  fillMPMList(pu, mpm, NUM_MOST_PROBABLE_MODES, numCand);
+#if JVET_AD0085_MPM_SORTING
+  if (!pu.cs->pcv->isEncoder && (pu.mpmFlag || pu.secondMpmFlag))
+  {
+    return numCand;
+  }
+#endif
+  fillNonMPMList(mpm, non_mpm);
+
+  return numCand;
+#else
 #if SECONDARY_MPM
   bool includedMode[NUM_INTRA_MODE];
   memset(includedMode, false, sizeof(includedMode));
@@ -1240,6 +1272,56 @@ int PU::getIntraMPMs(const PredictionUnit &pu, unsigned* mpm, const ChannelType
       }
     }
 #endif
+#if JVET_AD0085_MPM_SORTING
+    if (pu.cs->sps->getUseMpmSorting())
+    {
+#if ENABLE_DIMD
+      //adding dimd modes
+      if (pu.cu->slice->getSPS()->getUseDimd())
+      {
+        if (pu.cu->dimdMode != -1)
+        {
+          mpm[numValidMPM] = pu.cu->dimdMode;
+          if (!includedMode[mpm[numValidMPM]])
+          {
+            includedMode[mpm[numValidMPM++]] = true;
+          }
+
+          for (int i = 0; i < DIMD_FUSION_NUM - 2; i++)
+          {
+            if (pu.cu->dimdBlendMode[i] != -1)
+            {
+              mpm[numValidMPM] = pu.cu->dimdBlendMode[i];
+              if (!includedMode[mpm[numValidMPM]])
+              {
+                includedMode[mpm[numValidMPM++]] = true;
+              }
+            }
+          }
+        }
+      }
+#endif
+
+      numCand = numValidMPM;
+
+      if (pIntraPred && numValidMPM > 2)
+      {
+        pIntraPred->deriveMPMSorted(pu, mpm, numValidMPM, 1);
+
+        if (!pu.cs->pcv->isEncoder && pu.mpmFlag && pu.ipredIdx < numValidMPM)
+        {
+          return numCand;
+        }
+
+        numCand = numValidMPM;
+        memset(includedMode, false, sizeof(includedMode));
+        for (int i = 0; i < numValidMPM; i++)
+        {
+          includedMode[mpm[i]] = true;
+        }
+      }
+    }
+#endif
 
     CHECK(2 >= numMPMs, "Invalid number of most probable modes");
 
@@ -1247,6 +1329,10 @@ int PU::getIntraMPMs(const PredictionUnit &pu, unsigned* mpm, const ChannelType
     const int mod = offset + 3;
 
     {
+#if JVET_AD0085_MPM_SORTING
+      if (!pu.cs->sps->getUseMpmSorting())
+      {
+#endif
 #if SECONDARY_MPM
       numCand = numValidMPM;
 #else
@@ -1280,8 +1366,47 @@ int PU::getIntraMPMs(const PredictionUnit &pu, unsigned* mpm, const ChannelType
         }
       }
 #endif
+#if JVET_AD0085_MPM_SORTING
+      }
+#endif
 
 #if SECONDARY_MPM
+#if JVET_AD0085_MPM_SORTING
+      if (pu.cs->sps->getUseMpmSorting())
+      {
+        for (int i = 0; i < numCand && numValidMPM < numMPMs; i++)
+        {
+          if (mpm[i] <= DC_IDX)
+          {
+            continue;
+          }
+
+          for (int deltaAngular = 0; deltaAngular < 4 && numValidMPM < numMPMs; deltaAngular++)
+          {
+            // try to fill mode - (delta + 1)
+            mpm[numValidMPM] = ((mpm[i] + offset - deltaAngular) % mod) + 2;
+            if (!includedMode[mpm[numValidMPM]])
+            {
+              includedMode[mpm[numValidMPM++]] = true;
+            }
+
+            if (numValidMPM >= numMPMs)
+            {
+              break;
+            }
+
+            // try to fill mode + delta + 1
+            mpm[numValidMPM] = ((mpm[i] - 1 + deltaAngular) % mod) + 2;
+            if (!includedMode[mpm[numValidMPM]])
+            {
+              includedMode[mpm[numValidMPM++]] = true;
+            }
+          }
+        }
+      }
+      else
+      {
+#endif
       bool checkDCEnabled = false;
 
       // Derived modes of mpm[1]
@@ -1292,24 +1417,24 @@ int PU::getIntraMPMs(const PredictionUnit &pu, unsigned* mpm, const ChannelType
           for (int i = 0; i < 4 && numValidMPM < numMPMs; i++)
           {
             mpm[numValidMPM] = ((mpm[1] + offset - i) % mod) + 2;
-            if( !includedMode[mpm[numValidMPM]] )
+            if (!includedMode[mpm[numValidMPM]])
             {
               includedMode[mpm[numValidMPM++]] = true;
             }
 
-            if( numValidMPM >= numMPMs )
+            if (numValidMPM >= numMPMs)
             {
               break;
             }
 
             mpm[numValidMPM] = ((mpm[1] - 1 + i) % mod) + 2;
-            if( !includedMode[mpm[numValidMPM]] )
+            if (!includedMode[mpm[numValidMPM]])
             {
               includedMode[mpm[numValidMPM++]] = true;
             }
           }
         }
-        else if( mpm[1] == DC_IDX )
+        else if (mpm[1] == DC_IDX)
         {
           checkDCEnabled = true;
         }
@@ -1324,7 +1449,7 @@ int PU::getIntraMPMs(const PredictionUnit &pu, unsigned* mpm, const ChannelType
           for (int i = 0; i < 4 && numValidMPM < numMPMs; i++)
           {
             mpm[numValidMPM] = ((mpm[2] + offset - i) % mod) + 2;
-            if( !includedMode[mpm[numValidMPM]] )
+            if (!includedMode[mpm[numValidMPM]])
             {
               includedMode[mpm[numValidMPM++]] = true;
             }
@@ -1333,13 +1458,13 @@ int PU::getIntraMPMs(const PredictionUnit &pu, unsigned* mpm, const ChannelType
               break;
 
             mpm[numValidMPM] = ((mpm[2] - 1 + i) % mod) + 2;
-            if( !includedMode[mpm[numValidMPM]] )
+            if (!includedMode[mpm[numValidMPM]])
             {
               includedMode[mpm[numValidMPM++]] = true;
             }
           }
         }
-        else if( mpm[2] == DC_IDX )
+        else if (mpm[2] == DC_IDX)
         {
           checkDCEnabled = true;
         }
@@ -1352,23 +1477,26 @@ int PU::getIntraMPMs(const PredictionUnit &pu, unsigned* mpm, const ChannelType
         for (int i = 0; i < 3 && numValidMPM < numMPMs; i++)
         {
           mpm[numValidMPM] = ((mpm[3] + offset - i) % mod) + 2;
-          if( !includedMode[mpm[numValidMPM]] )
+          if (!includedMode[mpm[numValidMPM]])
           {
             includedMode[mpm[numValidMPM++]] = true;
           }
 
-          if( numValidMPM >= numMPMs )
+          if (numValidMPM >= numMPMs)
           {
             break;
           }
 
           mpm[numValidMPM] = ((mpm[3] - 1 + i) % mod) + 2;
-          if( !includedMode[mpm[numValidMPM]] )
+          if (!includedMode[mpm[numValidMPM]])
           {
             includedMode[mpm[numValidMPM++]] = true;
           }
         }
       }
+#if JVET_AD0085_MPM_SORTING
+      }
+#endif
 #else
       if (leftIntraDir == aboveIntraDir)
       {
@@ -1462,6 +1590,7 @@ int PU::getIntraMPMs(const PredictionUnit &pu, unsigned* mpm, const ChannelType
     CHECK(numCand == 0, "No candidates found");
     return numCand;
   }
+#endif
 }
 
 #if JVET_Y0065_GPM_INTRA
@@ -1589,6 +1718,12 @@ void PU::getGeoIntraMPMs( const PredictionUnit &pu, uint8_t* mpm, uint8_t splitD
       mpm[numValidMPM] = puLeft->cu->timd ? MAP131TO67(PU::getIntraDirLuma(*puLeft)) : PU::getIntraDirLuma(*puLeft);
 #else
       mpm[numValidMPM] = PU::getIntraDirLuma(*puLeft);
+#endif
+#if JVET_AD0085_TMRL_EXTENSION
+      if (puLeft->cu->tmrlFlag)
+      {
+        mpm[numValidMPM] = MAP131TO67(mpm[numValidMPM]);
+      }
 #endif
       if( !includedMode[mpm[numValidMPM]] )
       {
@@ -1610,6 +1745,12 @@ void PU::getGeoIntraMPMs( const PredictionUnit &pu, uint8_t* mpm, uint8_t splitD
       mpm[numValidMPM] = puAbove->cu->timd ? MAP131TO67(PU::getIntraDirLuma(*puAbove)) : PU::getIntraDirLuma(*puAbove);
 #else
       mpm[numValidMPM] = PU::getIntraDirLuma(*puAbove);
+#endif
+#if JVET_AD0085_TMRL_EXTENSION
+      if (puAbove->cu->tmrlFlag)
+      {
+        mpm[numValidMPM] = MAP131TO67(mpm[numValidMPM]);
+      }
 #endif
       if( !includedMode[mpm[numValidMPM]] )
       {
@@ -1667,6 +1808,12 @@ void PU::getGeoIntraMPMs( const PredictionUnit &pu, uint8_t* mpm, uint8_t splitD
       mpm[numValidMPM] = puBelowLeft->cu->timd ? MAP131TO67(PU::getIntraDirLuma(*puBelowLeft)) : PU::getIntraDirLuma(*puBelowLeft);
 #else
       mpm[numValidMPM] = PU::getIntraDirLuma(*puBelowLeft);
+#endif
+#if JVET_AD0085_TMRL_EXTENSION
+      if (puBelowLeft->cu->tmrlFlag)
+      {
+        mpm[numValidMPM] = MAP131TO67(mpm[numValidMPM]);
+      }
 #endif
       if( !includedMode[mpm[numValidMPM]] )
       {
@@ -1688,6 +1835,12 @@ void PU::getGeoIntraMPMs( const PredictionUnit &pu, uint8_t* mpm, uint8_t splitD
       mpm[numValidMPM] = puAboveRight->cu->timd ? MAP131TO67(PU::getIntraDirLuma(*puAboveRight)) : PU::getIntraDirLuma(*puAboveRight);
 #else
       mpm[numValidMPM] = PU::getIntraDirLuma(*puAboveRight);
+#endif
+#if JVET_AD0085_TMRL_EXTENSION
+      if (puAboveRight->cu->tmrlFlag)
+      {
+        mpm[numValidMPM] = MAP131TO67(mpm[numValidMPM]);
+      }
 #endif
       if( !includedMode[mpm[numValidMPM]] )
       {
@@ -1708,6 +1861,12 @@ void PU::getGeoIntraMPMs( const PredictionUnit &pu, uint8_t* mpm, uint8_t splitD
       mpm[numValidMPM] = puAboveLeft->cu->timd ? MAP131TO67(PU::getIntraDirLuma(*puAboveLeft)) : PU::getIntraDirLuma(*puAboveLeft);
 #else
       mpm[numValidMPM] = PU::getIntraDirLuma(*puAboveLeft);
+#endif
+#if JVET_AD0085_TMRL_EXTENSION
+      if (puAboveLeft->cu->tmrlFlag)
+      {
+        mpm[numValidMPM] = MAP131TO67(mpm[numValidMPM]);
+      }
 #endif
       if( !includedMode[mpm[numValidMPM]] )
       {
@@ -1877,6 +2036,12 @@ void PU::getSgpmIntraMPMs(const PredictionUnit &pu, uint8_t *mpm, uint8_t splitD
       mpm[numValidMPM] = puLeft->cu->timd ? MAP131TO67(PU::getIntraDirLuma(*puLeft)) : PU::getIntraDirLuma(*puLeft);
 #else
       mpm[numValidMPM] = PU::getIntraDirLuma(*puLeft);
+#endif
+#if JVET_AD0085_TMRL_EXTENSION
+      if (puLeft->cu->tmrlFlag)
+      {
+        mpm[numValidMPM] = MAP131TO67(mpm[numValidMPM]);
+      }
 #endif
       if (!includedMode[mpm[numValidMPM]])
       {
@@ -1898,6 +2063,12 @@ void PU::getSgpmIntraMPMs(const PredictionUnit &pu, uint8_t *mpm, uint8_t splitD
       mpm[numValidMPM] = puAbove->cu->timd ? MAP131TO67(PU::getIntraDirLuma(*puAbove)) : PU::getIntraDirLuma(*puAbove);
 #else
       mpm[numValidMPM] = PU::getIntraDirLuma(*puAbove);
+#endif
+#if JVET_AD0085_TMRL_EXTENSION
+      if (puAbove->cu->tmrlFlag)
+      {
+        mpm[numValidMPM] = MAP131TO67(mpm[numValidMPM]);
+      }
 #endif
       if (!includedMode[mpm[numValidMPM]])
       {
@@ -1964,6 +2135,12 @@ void PU::getSgpmIntraMPMs(const PredictionUnit &pu, uint8_t *mpm, uint8_t splitD
         puBelowLeft->cu->timd ? MAP131TO67(PU::getIntraDirLuma(*puBelowLeft)) : PU::getIntraDirLuma(*puBelowLeft);
 #else
       mpm[numValidMPM] = PU::getIntraDirLuma(*puBelowLeft);
+#endif
+#if JVET_AD0085_TMRL_EXTENSION
+      if (puBelowLeft->cu->tmrlFlag)
+      {
+        mpm[numValidMPM] = MAP131TO67(mpm[numValidMPM]);
+      }
 #endif
       if (!includedMode[mpm[numValidMPM]])
       {
@@ -1986,6 +2163,12 @@ void PU::getSgpmIntraMPMs(const PredictionUnit &pu, uint8_t *mpm, uint8_t splitD
         puAboveRight->cu->timd ? MAP131TO67(PU::getIntraDirLuma(*puAboveRight)) : PU::getIntraDirLuma(*puAboveRight);
 #else
       mpm[numValidMPM] = PU::getIntraDirLuma(*puAboveRight);
+#endif
+#if JVET_AD0085_TMRL_EXTENSION
+      if (puAboveRight->cu->tmrlFlag)
+      {
+        mpm[numValidMPM] = MAP131TO67(mpm[numValidMPM]);
+      }
 #endif
       if (!includedMode[mpm[numValidMPM]])
       {
@@ -2007,6 +2190,12 @@ void PU::getSgpmIntraMPMs(const PredictionUnit &pu, uint8_t *mpm, uint8_t splitD
         puAboveLeft->cu->timd ? MAP131TO67(PU::getIntraDirLuma(*puAboveLeft)) : PU::getIntraDirLuma(*puAboveLeft);
 #else
       mpm[numValidMPM] = PU::getIntraDirLuma(*puAboveLeft);
+#endif
+#if JVET_AD0085_TMRL_EXTENSION
+      if (puAboveLeft->cu->tmrlFlag)
+      {
+        mpm[numValidMPM] = MAP131TO67(mpm[numValidMPM]);
+      }
 #endif
       if (!includedMode[mpm[numValidMPM]])
       {
@@ -2343,6 +2532,28 @@ bool PU::hasChromaBvFlag(const PredictionUnit &pu)
 }
 #endif
 
+#if JVET_AD0085_MPM_SORTING
+bool PU::allowMPMSorted(const PredictionUnit& pu)
+{
+  if (!pu.cs->sps->getUseMpmSorting())
+  {
+    return false;
+  }
+
+  const Area area = pu.Y();
+
+#if JVET_AD0085_TMRL_EXTENSION
+  if ((pu.cs->slice->getSliceType() == I_SLICE && area.width * area.height > 128) || (area.width * area.height > 1024))
+#else
+  if ((pu.cs->slice->getSliceType() == I_SLICE && area.width * area.height > 32) || (area.width * area.height > 1024))
+#endif
+  {
+    return false;
+  }
+  return true;
+}
+#endif
+
 #if JVET_AB0155_SGPM
 bool PU::isSgpm(const PredictionUnit &pu, const ChannelType &chType)
 {
@@ -2622,6 +2833,12 @@ uint32_t PU::getCoLocatedIntraLumaMode(const PredictionUnit &pu, const int partI
   {
     return MAP131TO67(PU::getIntraDirLuma(PU::getCoLocatedLumaPU(pu), partIdx));
   }
+#endif
+#if JVET_AD0085_TMRL_EXTENSION
+  if (PU::getCoLocatedLumaPU(pu).cu->tmrlFlag)
+  {
+    return MAP131TO67(PU::getIntraDirLuma(PU::getCoLocatedLumaPU(pu), partIdx));
+  }
 #endif
   return PU::getIntraDirLuma(PU::getCoLocatedLumaPU(pu), partIdx);
 }
@@ -16136,6 +16353,12 @@ void PU::spanIpmInfoIntra( PredictionUnit &pu)
   {
     ipm = MAP131TO67(ipm);
   }
+#if JVET_AD0085_TMRL_EXTENSION
+  if (pu.cu->tmrlFlag)
+  {
+    ipm = MAP131TO67(ipm);
+  }
+#endif
   IpmBuf ib = pu.getIpmBuf();
   ib.fill(ipm);
 }
@@ -19306,7 +19529,12 @@ uint32_t PU::getFinalIntraModeForTransform( const TransformUnit &tu, const Compo
     intraMode = PLANAR_IDX;
   }
 #endif
-
+#if JVET_AD0085_TMRL_EXTENSION
+  if (tu.cu->tmrlFlag && compID == COMPONENT_Y)
+  {
+    intraMode = MAP131TO67(intraMode);
+  }
+#endif
   CHECK( intraMode >= NUM_INTRA_MODE - 1, "Invalid intra mode" );
 
   intraMode = PU::getNSPTIntraMode( PU::getWideAngle( tu, intraMode, compID ) );
@@ -19355,3 +19583,274 @@ bool CU::nsptApplyCond( const TransformUnit& tu, ComponentID compID, bool allowN
   return cond;
 }
 #endif
+
+#if JVET_AD0085_TMRL_EXTENSION
+int getSpatialIpm(const PredictionUnit& pu, uint8_t* spatialIpm, const int maxCands
+#if JVET_AC0094_REF_SAMPLES_OPT
+  , const bool& isForcedValid
+#endif
+  , bool extPrecision
+#if JVET_AD0085_MPM_SORTING
+  , IntraPrediction* pIntraPred/* = nullptr*/
+#endif
+)
+{
+#if JVET_AC0094_REF_SAMPLES_OPT
+  uint8_t arrayReserved[NUM_LUMA_MODE];
+  int     nbReserved{ 0 };
+#endif
+  bool includedMode[EXT_VDIA_IDX + 1]{ false };
+  includedMode[PLANAR_IDX] = true;
+  const CompArea& area = pu.block(COMPONENT_Y);
+  const Position topLeft = area.topLeft();
+  int numCand = 0;
+  const ChannelType channelType = CHANNEL_TYPE_LUMA;
+  auto getIpm = [&](Position pos) -> void
+  {
+    if (numCand >= maxCands)
+    {
+      return;
+    }
+    const PredictionUnit* neighborPu = pu.cs->getPURestricted(pos, pu, channelType);
+    if (neighborPu)
+    {
+      bool found = false;
+      if (CU::isIntra(*neighborPu->cu))
+      {
+        auto neighborMode = PU::getIntraDirLuma(*neighborPu);
+        if (neighborPu->cu->sgpm)
+        {
+          neighborMode = g_geoAngle2IntraAng[g_geoParams[neighborPu->cu->sgpmSplitDir][0]];;
+        }
+#if JVET_AD0085_TMRL_EXTENSION
+        if (extPrecision)
+        {
+          spatialIpm[numCand] = (neighborPu->cu->timd || neighborPu->cu->tmrlFlag) ? neighborMode : MAP67TO131(neighborMode);
+        }
+        else
+        {
+          spatialIpm[numCand] = (neighborPu->cu->timd || neighborPu->cu->tmrlFlag) ? MAP131TO67(neighborMode) : neighborMode;
+        }
+#else
+        spatialIpm[numCand] = neighborPu->cu->timd ? MAP131TO67(neighborMode) : neighborMode;
+#endif
+        found = true;
+      }
+      if (CU::isInter(*neighborPu->cu) || CU::isIBC(*neighborPu->cu))
+      {
+        spatialIpm[numCand] = neighborPu->getIpmInfo(pos);
+        if (neighborPu->cu->geoFlag)
+        {
+          spatialIpm[numCand] = g_geoAngle2IntraAng[g_geoParams[neighborPu->geoSplitDir][0]];
+        }
+#if JVET_AD0085_TMRL_EXTENSION
+        if (extPrecision)
+        {
+          spatialIpm[numCand] = MAP67TO131(spatialIpm[numCand]);
+        }
+#endif
+        found = true;
+      }
+      if (found && !includedMode[spatialIpm[numCand]])
+      {
+#if JVET_AC0094_REF_SAMPLES_OPT
+        if (CU::isIdxModeValid((pu.cu)->areAboveRightUnavail, (pu.cu)->areBelowLeftUnavail,
+          (pu.cu)->lheight(), (pu.cu)->lwidth(), extPrecision ? MAP131TO67(spatialIpm[numCand]) : spatialIpm[numCand], isForcedValid))
+        {
+#endif
+          if (!includedMode[spatialIpm[numCand]])
+          {
+            includedMode[spatialIpm[numCand++]] = true;
+          }
+#if JVET_AC0094_REF_SAMPLES_OPT
+        }
+        else
+        {
+          arrayReserved[nbReserved] = spatialIpm[numCand];
+          nbReserved++;
+        }
+#endif
+      }
+    }
+  };
+
+  // add spatial positions
+  getIpm(topLeft.offset(-1, pu.Y().height - 1));
+  getIpm(topLeft.offset(pu.Y().width - 1, -1));
+  getIpm(topLeft.offset(-1, -1));
+  getIpm(topLeft.offset(pu.Y().width, -1));
+  getIpm(topLeft.offset(-1, pu.Y().height));
+
+#if SECONDARY_MPM
+  //adding dimd modes
+  if (pu.cu->slice->getSPS()->getUseDimd())
+  {
+    if (pu.cu->dimdMode != -1 && numCand < maxCands)
+    {
+      auto currMode = pu.cu->dimdMode;
+      if (extPrecision)
+      {
+        currMode = MAP67TO131(currMode);
+      }
+      spatialIpm[numCand] = currMode;
+      if (!includedMode[spatialIpm[numCand]])
+      {
+        includedMode[spatialIpm[numCand++]] = true;
+      }
+    }
+
+    if (pu.cu->dimdBlendMode[0] != -1 && numCand < maxCands)
+    {
+      auto currMode = pu.cu->dimdBlendMode[0];
+      if (extPrecision)
+      {
+        currMode = MAP67TO131(currMode);
+      }
+      spatialIpm[numCand] = currMode;
+      if (!includedMode[spatialIpm[numCand]])
+      {
+        includedMode[spatialIpm[numCand++]] = true;
+      }
+    }
+  }
+#endif
+
+  // non-adjacent spatial candidates
+  int offsetX = 0;
+  int offsetY = 0;
+  const int numNACandidate[4] = { 3, 5, 5, 5 };
+  const int idxMap[4][5] = { { 0, 1, 4 },{ 0, 1, 2, 3, 4 },{ 0, 1, 2, 3, 4 },{ 0, 1, 2, 3, 4 } };
+  for (int iDistanceIndex = 0; iDistanceIndex < NADISTANCE_LEVEL; iDistanceIndex++)
+  {
+    const int iNADistanceHor = pu.Y().width * (iDistanceIndex + 1);
+    const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1);
+
+    for (int iNASPIdx = 0; iNASPIdx < numNACandidate[iDistanceIndex]; iNASPIdx++)
+    {
+      switch (idxMap[iDistanceIndex][iNASPIdx])
+      {
+      case 0:offsetX = -iNADistanceHor - 1; offsetY = pu.Y().height + iNADistanceVer - 1; break;
+      case 1:offsetX = pu.Y().width + iNADistanceHor - 1; offsetY = -iNADistanceVer - 1; break;
+      case 2:offsetX = pu.Y().width >> 1;   offsetY = -iNADistanceVer - 1;    break;
+      case 3:offsetX = -iNADistanceHor - 1; offsetY = pu.Y().height >> 1; break;
+      case 4:offsetX = -iNADistanceHor - 1; offsetY = -iNADistanceVer - 1;    break;
+      default: printf("error!"); exit(0); break;
+      }
+      getIpm(topLeft.offset(offsetX, offsetY));
+    }
+  }
+#if JVET_AD0085_MPM_SORTING
+  if (pIntraPred && numCand > ((pu.cs->slice->getSliceType() == I_SLICE) ? NUM_PRIMARY_MOST_PROBABLE_MODES - 1 : 1))
+  {
+    pIntraPred->deriveMPMSorted(pu, spatialIpm, numCand, 0);
+  }
+#endif
+
+#if JVET_AC0094_REF_SAMPLES_OPT
+  if (!isForcedValid)
+  {
+    for (int i{ 0 }; i < nbReserved && numCand < maxCands; i++)
+    {
+      auto currMode = arrayReserved[i];
+      if (!includedMode[currMode])
+      {
+        spatialIpm[numCand] = currMode;
+        includedMode[currMode] = true;
+        numCand++;
+      }
+    }
+  }
+#endif
+
+  CHECK(numCand > maxCands, "");
+
+  return numCand;
+}
+
+void fillMPMList(const PredictionUnit& pu, uint8_t* mpm, const int maxCands, const int numCand, bool extPrecision)
+{
+  if (numCand >= maxCands)
+  {
+    return;
+  }
+
+  bool includedMode[EXT_VDIA_IDX + 1]{ false };
+  CHECK(numCand > maxCands, "");
+  int idx = 0;
+  for (; idx < numCand; idx++)
+  {
+    includedMode[mpm[idx]] = true;
+  }
+
+  const int currNumCands = idx;
+  const int offset = extPrecision ? EXT_VDIA_IDX - 5 : NUM_LUMA_MODE - 6;
+  const int mod = offset + 3;
+  for (int i = 0; i < currNumCands; i++)
+  {
+    if (mpm[i] <= DC_IDX)
+    {
+      continue;
+    }
+    for (int deltaAngular = 0; deltaAngular < 4; deltaAngular++)
+    {
+      if (idx < maxCands)
+      {
+        auto mode = ((mpm[i] + offset - deltaAngular) % mod) + 2;
+        if (!includedMode[mode])
+        {
+          includedMode[mode] = true;
+          mpm[idx++] = mode;
+        }
+      }
+
+      if (idx < maxCands)
+      {
+        auto mode = ((mpm[i] - 1 + deltaAngular) % mod) + 2;
+        if (!includedMode[mode])
+        {
+          includedMode[mode] = true;
+          mpm[idx++] = mode;
+        }
+      }
+    }
+  }
+
+  uint8_t mpmDefault[] = { DC_IDX, VER_IDX, HOR_IDX, VER_IDX - 4, VER_IDX + 4, 14, 22, 42, 58, 10, 26,
+                            38, 62, 6, 30, 34, 66, 2, 48, 52, 16 };
+  for (int i = 0; idx < maxCands; i++)
+  {
+    auto mode = mpmDefault[i];
+    if (extPrecision)
+    {
+      mode = MAP67TO131(mode);
+    }
+    if (!includedMode[mode])
+    {
+      includedMode[mode] = true;
+      mpm[idx++] = mode;
+    }
+  }
+  CHECK(idx != maxCands, "");
+}
+
+void fillNonMPMList(uint8_t* mpm, uint8_t* non_mpm)
+{
+  bool includedMode[EXT_VDIA_IDX + 1]{ false };
+  for (int i = 0; i < NUM_MOST_PROBABLE_MODES; i++)
+  {
+    auto mode = mpm[i];
+    includedMode[mode] = true;
+    CHECK(mode < PLANAR_IDX || mode >= NUM_LUMA_MODE, "");
+  }
+
+  int numNonMPM = 0;
+  for (int i = 0; i < NUM_LUMA_MODE; i++)
+  {
+    if (!includedMode[i] && numNonMPM < NUM_NON_MPM_MODES)
+    {
+      non_mpm[numNonMPM++] = i;
+    }
+  }
+  CHECK(numNonMPM != NUM_LUMA_MODE - NUM_MOST_PROBABLE_MODES, "");
+}
+#endif
diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h
index 6fc19688dc8d06e8748ea1605063f1538aea9e15..12d0140ec89fa1fbbfdae32958663efbd2deab0c 100644
--- a/source/Lib/CommonLib/UnitTools.h
+++ b/source/Lib/CommonLib/UnitTools.h
@@ -161,9 +161,12 @@ namespace PU
 #if SECONDARY_MPM
   int getIntraMPMs(const PredictionUnit &pu, uint8_t *mpm, uint8_t* non_mpm
 #if JVET_AC0094_REF_SAMPLES_OPT
-                   , const bool &isForcedValid
+                 , const bool &isForcedValid
 #endif
-      , const ChannelType &channelType = CHANNEL_TYPE_LUMA
+#if JVET_AD0085_MPM_SORTING
+                 , IntraPrediction* pIntraPred = nullptr
+#endif
+                 , const ChannelType &channelType = CHANNEL_TYPE_LUMA
   );
 #else
   int  getIntraMPMs(const PredictionUnit &pu, unsigned *mpm, const ChannelType &channelType = CHANNEL_TYPE_LUMA);
@@ -667,6 +670,9 @@ namespace PU
 #if JVET_AC0144_AFFINE_DMVR_REGRESSION
   void deriveAffineCandFromMvField(Position posLT, const int width, const int height, std::vector<RMVFInfo> mvInfoVec, Mv mvAffi[3]);
 #endif
+#if JVET_AD0085_MPM_SORTING
+  bool allowMPMSorted(const PredictionUnit& pu);
+#endif
 }
 
 // TU tools
@@ -1065,4 +1071,17 @@ bool storeContexts( const Slice* slice, const int ctuXPosInCtus, const int ctuYP
 #if JVET_AC0144_AFFINE_DMVR_REGRESSION
 int deriveAffineSubBlkSize(const int sz, const int minSbSz, const int deltaMvX, const int deltaMvY, const int shift);
 #endif
+#if JVET_AD0085_TMRL_EXTENSION
+int getSpatialIpm(const PredictionUnit& pu, uint8_t* spatialIpm, const int maxCands
+#if JVET_AC0094_REF_SAMPLES_OPT
+                , const bool& isForcedValid
+#endif
+                , bool extPrecision = false
+#if JVET_AD0085_MPM_SORTING
+                , IntraPrediction* pIntraPred = nullptr
+#endif
+);
+void fillMPMList(const PredictionUnit& pu, uint8_t* mpm, const int numToFill, const int numCand, bool extPrecision = false);
+void fillNonMPMList(uint8_t* mpm, uint8_t* non_mpm);
+#endif
 #endif
diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp
index d8e8dbee039d8d51b5a4e778ed3ca692ffcf58fa..9fc240c3dd6fb19f8c27b96d08c7c98818698975 100644
--- a/source/Lib/DecoderLib/CABACReader.cpp
+++ b/source/Lib/DecoderLib/CABACReader.cpp
@@ -2114,6 +2114,7 @@ void CABACReader::intra_luma_pred_modes( CodingUnit &cu )
 
   for( int k = 0; k < numBlocks; k++ )
   {
+#if !JVET_AD0085_TMRL_EXTENSION
 #if SECONDARY_MPM
     PU::getIntraMPMs( *pu, mpmPred, nonMpmPred
 #if JVET_AC0094_REF_SAMPLES_OPT
@@ -2123,6 +2124,7 @@ void CABACReader::intra_luma_pred_modes( CodingUnit &cu )
 #else
     PU::getIntraMPMs(*pu, mpmPred);
 #endif
+#endif
 #if ENABLE_DIMD || JVET_W0123_TIMD_FUSION
     pu->parseLumaMode = true;
     pu->mpmFlag = mpmFlag[k];
@@ -2179,7 +2181,33 @@ void CABACReader::intra_luma_pred_modes( CodingUnit &cu )
       if( m_BinDecoder.decodeBin( Ctx::IntraLumaSecondMpmFlag() ) )
       {
 #if ENABLE_DIMD || JVET_W0123_TIMD_FUSION
+#if JVET_AD0085_MPM_SORTING
+        int idx = 0;
+        if (cu.cs->sps->getUseMpmSorting())
+        {
+          const int maxNumCtxBins = (NUM_SECONDARY_MOST_PROBABLE_MODES / 4) - 1;
+          int prefixIdx = 0;
+          int ctxId = 0;
+          for (int val = 0; val < maxNumCtxBins; val++)
+          {
+            unsigned int bin = m_BinDecoder.decodeBin(Ctx::IntraLumaSecondMpmIdx(ctxId++));
+            prefixIdx += bin;
+            if (!bin)
+            {
+              break;
+            }
+          }
+
+          idx = m_BinDecoder.decodeBinsEP(2) + prefixIdx * 4;
+          idx += NUM_PRIMARY_MOST_PROBABLE_MODES;
+        }
+        else
+        {
+          idx = m_BinDecoder.decodeBinsEP(4) + NUM_PRIMARY_MOST_PROBABLE_MODES;
+        }
+#else
         int idx = m_BinDecoder.decodeBinsEP( 4 ) + NUM_PRIMARY_MOST_PROBABLE_MODES;
+#endif
         ipredMode = mpmPred[idx];
         pu->secondMpmFlag = true;
         pu->ipredIdx = idx;
diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp
index 3844cc29a47a0fbe356a4530e22127a71e1b4f82..3aeed0856a64145ace2f42ddd5af162b84d39248 100644
--- a/source/Lib/DecoderLib/DecCu.cpp
+++ b/source/Lib/DecoderLib/DecCu.cpp
@@ -380,11 +380,27 @@ void DecCu::decompressCtu( CodingStructure& cs, const UnitArea& ctuArea )
 #if SECONDARY_MPM
           uint8_t* mpmPred = currCU.firstPU->intraMPM;  // mpm_idx / rem_intra_luma_pred_mode
           uint8_t* nonMpmPred = currCU.firstPU->intraNonMPM;
+#if JVET_AD0085_MPM_SORTING
+          if (PU::allowMPMSorted(*currCU.firstPU) && !(currCU.firstPU->mpmFlag && currCU.firstPU->ipredIdx == 0))
+          {
+            PU::getIntraMPMs(*currCU.firstPU, mpmPred, nonMpmPred
+#if JVET_AC0094_REF_SAMPLES_OPT
+                           , true
+#endif
+                           , m_pcIntraPred
+            );
+          }
+          else
+          {
+#endif
           PU::getIntraMPMs( *currCU.firstPU, mpmPred, nonMpmPred
 #if JVET_AC0094_REF_SAMPLES_OPT
                            , false
 #endif
           );
+#if JVET_AD0085_MPM_SORTING
+          }
+#endif
 #else
           unsigned int mpmPred[NUM_MOST_PROBABLE_MODES];  // mpm_idx / rem_intra_luma_pred_mode
           PU::getIntraMPMs(*currCU.firstPU, mpmPred);
diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp
index d5519cf55028452edd2a58b0066f85d18c3293d7..ef815682b64b74e772ff72e6a33a607ec7c70cbc 100644
--- a/source/Lib/DecoderLib/VLCReader.cpp
+++ b/source/Lib/DecoderLib/VLCReader.cpp
@@ -2544,6 +2544,9 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
 #if JVET_AD0082_TMRL_CONFIG
   READ_FLAG(uiCode, "sps_tmrl_enabled_flag");                       pcSPS->setUseTmrl(uiCode != 0);
 #endif
+#if JVET_AD0085_MPM_SORTING
+  READ_FLAG(uiCode, "sps_mpm_sorting_enabled_flag");                pcSPS->setUseMpmSorting(uiCode != 0);
+#endif
 #if JVET_AC0147_CCCM_NO_SUBSAMPLING
   READ_UVLC(uiCode, "sps_cccm_cand");                               pcSPS->setUseCccm(uiCode);
 #endif
diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp
index c317b3051640f446f8ac96133c6071c9020055d5..c56e8819dec15839afe0858d6a7892228fdb875c 100644
--- a/source/Lib/EncoderLib/CABACWriter.cpp
+++ b/source/Lib/EncoderLib/CABACWriter.cpp
@@ -1686,7 +1686,31 @@ void CABACWriter::intra_luma_pred_modes( const CodingUnit& cu )
         if( secondaryMPMIdx < NUM_SECONDARY_MOST_PROBABLE_MODES )
         {
           m_BinEncoder.encodeBin(1, Ctx::IntraLumaSecondMpmFlag());
+#if JVET_AD0085_MPM_SORTING
+          if (cu.cs->sps->getUseMpmSorting())
+          {
+            int ctxId = 0;
+            const int maxNumCtxBins = (NUM_SECONDARY_MOST_PROBABLE_MODES / 4) - 1;
+            int prefixIdx = secondaryMPMIdx / 4;
+            for (int val = 0; val < maxNumCtxBins; val++)
+            {
+              unsigned int bin = (val == prefixIdx ? 0 : 1);
+              m_BinEncoder.encodeBin(bin, Ctx::IntraLumaSecondMpmIdx(ctxId++));
+              if (!bin)
+              {
+                break;
+              }
+            }
+
+            m_BinEncoder.encodeBinsEP(secondaryMPMIdx - prefixIdx * 4, 2);
+          }
+          else
+          {
+#endif
           m_BinEncoder.encodeBinsEP( secondaryMPMIdx, 4);
+#if JVET_AD0085_MPM_SORTING
+          }
+#endif
 #if ENABLE_TRACING && (ENABLE_DIMD || JVET_W0123_TIMD_FUSION)
           pred_idx = secondaryMPMIdx + NUM_PRIMARY_MOST_PROBABLE_MODES;
           secondMpmFlag = true;
@@ -1893,21 +1917,45 @@ void CABACWriter::intra_luma_pred_mode( const PredictionUnit& pu )
     { 
 #if SECONDARY_MPM
       auto secondMpmPred = mpmPred + NUM_PRIMARY_MOST_PROBABLE_MODES;
-      unsigned   second_mpm_idx = NUM_SECONDARY_MOST_PROBABLE_MODES;
+      unsigned   secondMpmIdx = NUM_SECONDARY_MOST_PROBABLE_MODES;
 
       for (unsigned idx = 0; idx < NUM_SECONDARY_MOST_PROBABLE_MODES; idx++)
       {
         if (ipredMode == secondMpmPred[idx])
         {
-          second_mpm_idx = idx;
+          secondMpmIdx = idx;
           break;
         }
       }
 
-      if (second_mpm_idx < NUM_SECONDARY_MOST_PROBABLE_MODES)
+      if (secondMpmIdx < NUM_SECONDARY_MOST_PROBABLE_MODES)
       {
         m_BinEncoder.encodeBin(1, Ctx::IntraLumaSecondMpmFlag());
-        m_BinEncoder.encodeBinsEP(second_mpm_idx, 4);
+#if JVET_AD0085_MPM_SORTING
+        if (pu.cs->sps->getUseMpmSorting())
+        {
+          int ctxId = 0;
+          const int maxNumCtxBins = (NUM_SECONDARY_MOST_PROBABLE_MODES / 4) - 1;
+          int prefixIdx = secondMpmIdx / 4;
+          for (int val = 0; val < maxNumCtxBins; val++)
+          {
+            unsigned int bin = (val == prefixIdx ? 0 : 1);
+            m_BinEncoder.encodeBin(bin, Ctx::IntraLumaSecondMpmIdx(ctxId++));
+            if (!bin)
+            {
+              break;
+            }
+          }
+
+          m_BinEncoder.encodeBinsEP(secondMpmIdx - prefixIdx * 4, 2);
+        }
+        else
+        {
+#endif
+        m_BinEncoder.encodeBinsEP(secondMpmIdx, 4);
+#if JVET_AD0085_MPM_SORTING
+        }
+#endif
       }
       else
       {
diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h
index 7a3387b5c71e81a237c1d09aa983cfd08c4bbb70..71aacf2e365dcd08c58c5a397d553763cffc01b5 100644
--- a/source/Lib/EncoderLib/EncCfg.h
+++ b/source/Lib/EncoderLib/EncCfg.h
@@ -479,6 +479,9 @@ protected:
 #if JVET_AD0082_TMRL_CONFIG
   bool      m_tmrl;
 #endif
+#if JVET_AD0085_MPM_SORTING
+  bool      m_mpmSorting;
+#endif
 #if JVET_AC0147_CCCM_NO_SUBSAMPLING
   int       m_cccm;
 #endif
@@ -1581,6 +1584,10 @@ public:
   void      setUseTmrl                   (bool b)         { m_tmrl = b; }
   bool      getUseTmrl                   ()         const { return m_tmrl; }
 #endif
+#if JVET_AD0085_MPM_SORTING
+  void      setUseMpmSorting             (bool b)         { m_mpmSorting = b; }
+  bool      getUseMpmSorting             () const         { return m_mpmSorting; }
+#endif
 #if JVET_AC0147_CCCM_NO_SUBSAMPLING
   void      setUseCccm                   (int i)          { m_cccm = i; }
   int       getUseCccm                   () const         { return m_cccm; }
diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp
index 4dbfdfe66d1c10abb2ceff11916bda6afb4031a2..309190015d7ed0b4c673e98e59ba711265eb4df6 100644
--- a/source/Lib/EncoderLib/EncCu.cpp
+++ b/source/Lib/EncoderLib/EncCu.cpp
@@ -2436,11 +2436,27 @@ bool EncCu::xCheckRDCostIntra(CodingStructure *&tempCS, CodingStructure *&bestCS
     }
 
 #if SECONDARY_MPM
+#if JVET_AD0085_MPM_SORTING
+    if (PU::allowMPMSorted(pu))
+    {
+      m_pcIntraSearch->getMpmListSize() = PU::getIntraMPMs(pu, m_pcIntraSearch->getMPMList(), m_pcIntraSearch->getNonMPMList()
+#if JVET_AC0094_REF_SAMPLES_OPT
+                                                         , true
+#endif
+                                                         , m_pcIntraSearch
+      );
+    }
+    else
+    {
+#endif
     m_pcIntraSearch->getMpmListSize() = PU::getIntraMPMs(pu, m_pcIntraSearch->getMPMList(), m_pcIntraSearch->getNonMPMList()
 #if JVET_AC0094_REF_SAMPLES_OPT
                                                          , false
 #endif
-);
+      );
+#if JVET_AD0085_MPM_SORTING
+    }
+#endif
 #endif
   }
 #if JVET_Z0050_DIMD_CHROMA_FUSION && (JVET_AC0094_REF_SAMPLES_OPT)
diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp
index a6c3c032826874d5df8bb7e319738fd77a9fcd74..8201529c88b2baa38b7297e51c6dfc3cf0781ff8 100644
--- a/source/Lib/EncoderLib/EncLib.cpp
+++ b/source/Lib/EncoderLib/EncLib.cpp
@@ -1848,6 +1848,9 @@ void EncLib::xInitSPS( SPS& sps )
 #if JVET_AD0082_TMRL_CONFIG
   sps.setUseTmrl            ( m_tmrl );
 #endif
+#if JVET_AD0085_MPM_SORTING
+  sps.setUseMpmSorting      ( m_mpmSorting );
+#endif
 #if JVET_AC0147_CCCM_NO_SUBSAMPLING
   sps.setUseCccm            ( m_cccm );
 #endif
diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp
index 3801234fe3beb9b7646304a962bf8ce0108cc03e..39cb0b9d4cec3abae45cd00712f02e23225b2386 100644
--- a/source/Lib/EncoderLib/VLCWriter.cpp
+++ b/source/Lib/EncoderLib/VLCWriter.cpp
@@ -1605,6 +1605,9 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
 #if JVET_AD0082_TMRL_CONFIG
   WRITE_FLAG(pcSPS->getUseTmrl() ? 1 : 0, "sps_tmrl_enabled_flag");
 #endif
+#if JVET_AD0085_MPM_SORTING
+  WRITE_FLAG(pcSPS->getUseMpmSorting() ? 1 : 0, "sps_mpm_sorting_enabled_flag");
+#endif
 #if JVET_AC0147_CCCM_NO_SUBSAMPLING
   WRITE_UVLC(pcSPS->getUseCccm() , "sps_cccm_cand");
 #endif