diff --git a/source/Lib/CommonLib/Buffer.cpp b/source/Lib/CommonLib/Buffer.cpp
index 2d13333c..47b648e2 100644
--- a/source/Lib/CommonLib/Buffer.cpp
+++ b/source/Lib/CommonLib/Buffer.cpp
@@ -1151,6 +1151,46 @@ void AreaBuf<Pel>::rspSignal( const AreaBuf<Pel> &toReshape, std::vector<Pel>& p
   }
 }
 
+#if TEST_3_2
+template<>
+void AreaBuf<Pel>::flipSignal(bool isFlipHor)
+{
+  Pel *tempPel;
+  Size tSize(width, height);
+  tempPel       = new Pel[tSize.area()];
+  PelBuf tmpBuf = PelBuf(tempPel, tSize);
+  copyBufferCore(buf, stride, tmpBuf.buf, tmpBuf.stride, tmpBuf.width, tmpBuf.height);
+
+  Pel *dstbuf = buf;
+  Pel *srcbuf = tmpBuf.buf;
+  if (isFlipHor)
+  {
+    for (unsigned y = 0; y < height; y++)
+    {
+      for (unsigned x = 0; x < width; x++)
+      {
+        dstbuf[x] = srcbuf[width - 1 - x];
+      }
+      dstbuf += stride;
+      srcbuf += tmpBuf.stride;
+    }
+  }
+  else
+  {
+    for (unsigned y = 0; y < height; y++)
+    {
+      for (unsigned x = 0; x < width; x++)
+      {
+        dstbuf[x] = srcbuf[(height - 1 - y) * tmpBuf.stride + x];
+      }
+      dstbuf += stride;
+    }
+  }
+
+  delete[] tempPel;
+}
+#endif
+
 template<>
 void AreaBuf<Pel>::rspSignalAllAndSubtract( const AreaBuf<Pel> &buffer1, const AreaBuf<Pel> &buffer2, std::vector<Pel>& pLUT )
 {
diff --git a/source/Lib/CommonLib/Buffer.h b/source/Lib/CommonLib/Buffer.h
index d5024000..b0cae5d6 100644
--- a/source/Lib/CommonLib/Buffer.h
+++ b/source/Lib/CommonLib/Buffer.h
@@ -197,6 +197,10 @@ struct AreaBuf : public Size
 
   void toLast               ( const ClpRng& clpRng );
 
+#if TEST_3_2
+  void flipSignal(bool isFlipHor);
+#endif
+
   void rspSignal            ( std::vector<Pel>& pLUT );
   void rspSignal            ( const AreaBuf<const Pel>& other, std::vector<Pel>& pLUT );
   void rspSignal            ( const AreaBuf<Pel> &toReshape, std::vector<Pel>& pLUT );
diff --git a/source/Lib/CommonLib/ContextModelling.cpp b/source/Lib/CommonLib/ContextModelling.cpp
index 4301f583..ab425df8 100644
--- a/source/Lib/CommonLib/ContextModelling.cpp
+++ b/source/Lib/CommonLib/ContextModelling.cpp
@@ -324,6 +324,23 @@ unsigned DeriveCtx::CtxBMMrgFlag(const CodingUnit& cu)
   return ctxId;
 }
 #endif
+
+#if TEST_3_2
+unsigned DeriveCtx::CtxRribcFlipType(const CodingUnit& cu)
+{
+  const CodingStructure *cs = cu.cs;
+  unsigned ctxId = 0;
+
+  const CodingUnit *cuLeft = cs->getCURestricted(cu.lumaPos().offset(-1, 0), cu, CH_L);
+  ctxId = (cuLeft && cuLeft->predMode == MODE_IBC && !cuLeft->firstPU->mergeFlag && cuLeft->rribcFlipType) ? 1 : 0;
+
+  const CodingUnit *cuAbove = cs->getCURestricted(cu.lumaPos().offset(0, -1), cu, CH_L);
+  ctxId += (cuAbove && cuAbove->predMode == MODE_IBC && !cuAbove->firstPU->mergeFlag && cuAbove->rribcFlipType) ? 1 : 0;
+
+  return ctxId;
+}
+#endif
+
 unsigned DeriveCtx::CtxAffineFlag( const CodingUnit& cu )
 {
   const CodingStructure *cs = cu.cs;
@@ -499,7 +516,16 @@ void MergeCtx::setMergeInfo( PredictionUnit& pu, int candIdx )
     pu.addHypData.clear();
     pu.numMergedAddHyps = 0;
 #endif
+#if TEST_3_2
+    pu.cu->rribcFlipType = rribcFlipTypes[candIdx];
   }
+  else
+  {
+    pu.cu->rribcFlipType = 0;
+  }
+#else
+  }
+#endif
   pu.cu->BcwIdx = ( interDirNeighbours[candIdx] == 3 ) ? BcwIdx[candIdx] : BCW_DEFAULT;
 #if MULTI_HYP_PRED
   if (pu.ciipFlag
diff --git a/source/Lib/CommonLib/ContextModelling.h b/source/Lib/CommonLib/ContextModelling.h
index 1687101b..6ccce511 100644
--- a/source/Lib/CommonLib/ContextModelling.h
+++ b/source/Lib/CommonLib/ContextModelling.h
@@ -560,6 +560,9 @@ public:
   uint8_t       BcwIdx[NUM_MERGE_CANDS];
 #if INTER_LIC
   bool          LICFlags[NUM_MERGE_CANDS];
+#endif
+#if TEST_3_2
+  int       rribcFlipTypes[NUM_MERGE_CANDS];
 #endif
   unsigned char interDirNeighbours[NUM_MERGE_CANDS];
 #if MULTI_HYP_PRED
@@ -574,6 +577,9 @@ public:
   uint8_t       BcwIdx            [ MRG_MAX_NUM_CANDS      ];
 #if INTER_LIC
   bool          LICFlags          [ MRG_MAX_NUM_CANDS      ];
+#endif
+#if TEST_3_2
+  int rribcFlipTypes[MRG_MAX_NUM_CANDS];
 #endif
   unsigned char interDirNeighbours[ MRG_MAX_NUM_CANDS      ];
 #if MULTI_HYP_PRED
@@ -659,6 +665,9 @@ unsigned CtxAffineFlag( const CodingUnit& cu );
 #if JVET_X0049_ADAPT_DMVR
 unsigned CtxBMMrgFlag(const CodingUnit& cu);
 #endif
+#if TEST_3_2
+unsigned CtxRribcFlipType(const CodingUnit& cu);
+#endif
 unsigned CtxPredModeFlag( const CodingUnit& cu );
 unsigned CtxIBCFlag(const CodingUnit& cu);
 unsigned CtxMipFlag   ( const CodingUnit& cu );
diff --git a/source/Lib/CommonLib/Contexts.cpp b/source/Lib/CommonLib/Contexts.cpp
index 6753b760..5e2ce06d 100644
--- a/source/Lib/CommonLib/Contexts.cpp
+++ b/source/Lib/CommonLib/Contexts.cpp
@@ -1497,6 +1497,23 @@ const CtxSet ContextSetCfg::BMMergeFlag = ContextSetCfg::addCtxSet
   });
 #endif
 
+#if TEST_3_2
+const CtxSet ContextSetCfg::rribcFlipType = ContextSetCfg::addCtxSet
+({
+  {  48,  50,  50,  50, },
+  {  56,  50,  43,  28, },
+  { CNU, CNU, CNU, CNU, },
+  {   5,   5,   9,   5, },
+  {   5,   5,   5,   5, },
+  { DWS, DWS, DWS, DWS, },
+  {  18,  18,  25,  18, },
+  {  18,  18,  11,  18, },
+  { DWE, DWE, DWE, DWE, },
+  { 126, 126, 181, 126, },
+  { 117, 117, 110, 116, },
+  });
+#endif
+
 const CtxSet ContextSetCfg::AffineFlag = ContextSetCfg::addCtxSet
 ({
   {  19,   6,   7, },
@@ -3347,6 +3364,18 @@ const CtxSet ContextSetCfg::BMMergeFlag = ContextSetCfg::addCtxSet
 });
 #endif
 
+#if TEST_3_2
+const CtxSet ContextSetCfg::rribcFlipType = ContextSetCfg::addCtxSet
+({
+  { 25, CNU, CNU, CNU },
+  { 26, CNU, CNU, CNU },
+  { 35, CNU, CNU, CNU },
+  { 4, 4, 4, 4 },
+  { 4, 4, 4, 4 },
+  { 4, 4, 4, 4 }
+  });
+#endif
+
 const CtxSet ContextSetCfg::AffineFlag = ContextSetCfg::addCtxSet
 ({
 	{ 34, 27,  6 },
@@ -4683,6 +4712,17 @@ const CtxSet ContextSetCfg::BMMergeFlag = ContextSetCfg::addCtxSet
   { 4, 4, 4, 4 },
 });
 #endif
+
+#if TEST_3_2
+const CtxSet ContextSetCfg::rribcFlipType = ContextSetCfg::addCtxSet
+({
+ { 25, CNU, CNU, CNU },
+  { 26, CNU, CNU, CNU },
+  { CNU, CNU, CNU, CNU },
+  { 4, 4, 4, 4 },
+  });
+#endif
+
 const CtxSet ContextSetCfg::AffineFlag = ContextSetCfg::addCtxSet
 ({
   {  19,  13,   6, },
diff --git a/source/Lib/CommonLib/Contexts.h b/source/Lib/CommonLib/Contexts.h
index 51e70a89..984d0426 100644
--- a/source/Lib/CommonLib/Contexts.h
+++ b/source/Lib/CommonLib/Contexts.h
@@ -340,6 +340,9 @@ public:
 #if JVET_X0049_ADAPT_DMVR
   static const CtxSet   BMMergeFlag;
 #endif
+#if TEST_3_2
+  static const CtxSet   rribcFlipType;
+#endif
 #if JVET_Y0065_GPM_INTRA
   static const CtxSet   GPMIntraFlag;
 #endif
diff --git a/source/Lib/CommonLib/IbcHashMap.cpp b/source/Lib/CommonLib/IbcHashMap.cpp
index 1d1d6cf4..f593a343 100644
--- a/source/Lib/CommonLib/IbcHashMap.cpp
+++ b/source/Lib/CommonLib/IbcHashMap.cpp
@@ -243,7 +243,11 @@ void IbcHashMap::xxBuildPicHashMap(const PelUnitBuf& pic)
   }
 }
 
+#if TEST_3_2
+void IbcHashMap::rebuildPicHashMap(const PelUnitBuf &pic, bool isDualTree)
+#else
 void IbcHashMap::rebuildPicHashMap(const PelUnitBuf& pic)
+#endif
 {
   m_hash2Pos.clear();
 
@@ -252,9 +256,13 @@ void IbcHashMap::rebuildPicHashMap(const PelUnitBuf& pic)
   case CHROMA_400:
     xxBuildPicHashMap<CHROMA_400>(pic);
     break;
+#if TEST_3_2
+  case CHROMA_420: isDualTree ? xxBuildPicHashMap<CHROMA_400>(pic) :  xxBuildPicHashMap<CHROMA_420>(pic); break;
+#else
   case CHROMA_420:
     xxBuildPicHashMap<CHROMA_420>(pic);
     break;
+#endif
   case CHROMA_422:
     xxBuildPicHashMap<CHROMA_422>(pic);
     break;
@@ -267,8 +275,90 @@ void IbcHashMap::rebuildPicHashMap(const PelUnitBuf& pic)
   }
 }
 
+#if TEST_3_2
+void IbcHashMap::buildFlipHashTable(PredictionUnit &pu, unsigned int pos2HashCurPU[MAX_CU_SIZE][MAX_CU_SIZE], const int rribcFlipType)
+{
+  if (rribcFlipType == 0)
+  {
+    return;
+  }
+  for (int i = 0; i < MAX_CU_SIZE; i++)
+  {
+    std::fill_n(pos2HashCurPU[i], MAX_CU_SIZE, 0x1FF);
+  }
+  PelStorage m_tmpStorageCU;
+  m_tmpStorageCU.create(UnitArea(pu.chromaFormat, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE)));
+  const UnitArea tmpArea(pu.chromaFormat, Area(0, 0, pu.cs->getOrgBuf(pu).Y().width, pu.cs->getOrgBuf(pu).Y().height));
+  PelUnitBuf     flipCU = m_tmpStorageCU.getBuf(tmpArea);
+  if (CS::isDualITree(*pu.cs))
+  {
+    flipCU.Y().copyFrom(pu.cs->getOrgBuf(pu).Y());
+  }
+  else
+  {
+    flipCU.copyFrom(pu.cs->getOrgBuf(pu));
+  }
+  flipCU.Y().flipSignal(rribcFlipType == 1);
+  if (pu.chromaFormat != CHROMA_400 && !(CS::isDualITree(*pu.cs)))
+  {
+    flipCU.Cb().flipSignal(rribcFlipType == 1);
+    flipCU.Cr().flipSignal(rribcFlipType == 1);
+  }
+
+  const int  chromaScalingX     = getChannelTypeScaleX(CHANNEL_TYPE_CHROMA, pu.chromaFormat);
+  const int  chromaScalingY     = getChannelTypeScaleY(CHANNEL_TYPE_CHROMA, pu.chromaFormat);
+  const int  chromaMinBlkWidth  = MIN_PU_SIZE >> chromaScalingX;
+  const int  chromaMinBlkHeight = MIN_PU_SIZE >> chromaScalingY;
+  const Pel *pelY               = NULL;
+  const Pel *pelCb              = NULL;
+  const Pel *pelCr              = NULL;
+
+  Position pos;
+  for (pos.y = 0; pos.y < flipCU.Y().height; pos.y += MIN_PU_SIZE)
+  {
+    // row pointer
+    pelY = flipCU.Y().bufAt(0, pos.y);
+    if (pu.chromaFormat != CHROMA_400 && !(CS::isDualITree(*pu.cs)))
+    {
+      int chromaY = pos.y >> chromaScalingY;
+      pelCb       = flipCU.Cb().bufAt(0, chromaY);
+      pelCr       = flipCU.Cr().bufAt(0, chromaY);
+    }
+
+    for (pos.x = 0; pos.x < flipCU.Y().width; pos.x += MIN_PU_SIZE)
+    {
+      // 0x1FF is just an initial value
+      unsigned int hashValue = 0x1FF;
+
+      // luma part
+      hashValue = xxCalcBlockHash(&pelY[pos.x], flipCU.Y().stride, MIN_PU_SIZE, MIN_PU_SIZE, hashValue);
+
+      // chroma part
+      if (pu.chromaFormat != CHROMA_400 && !(CS::isDualITree(*pu.cs)))
+      {
+        int chromaX = pos.x >> chromaScalingX;
+        hashValue = xxCalcBlockHash(&pelCb[chromaX], flipCU.Cb().stride, chromaMinBlkWidth, chromaMinBlkHeight, hashValue);
+        hashValue = xxCalcBlockHash(&pelCr[chromaX], flipCU.Cr().stride, chromaMinBlkWidth, chromaMinBlkHeight, hashValue);
+      }
+
+      pos2HashCurPU[pos.y][pos.x] = hashValue;
+    }
+  }
+
+  m_tmpStorageCU.destroy();
+}
+
+bool IbcHashMap::ibcHashMatch(PredictionUnit &pu, const Area &lumaArea, std::vector<Position> &cand,
+                              const CodingStructure &cs, const int maxCand, const int searchRange4SmallBlk,
+                              const int rribcFlipType)
+{
+  unsigned int pos2HashCurPU[MAX_CU_SIZE][MAX_CU_SIZE];
+
+  buildFlipHashTable(pu, pos2HashCurPU, rribcFlipType);
+#else
 bool IbcHashMap::ibcHashMatch(const Area& lumaArea, std::vector<Position>& cand, const CodingStructure& cs, const int maxCand, const int searchRange4SmallBlk)
 {
+#endif
   cand.clear();
 
   // find the block with least candidates
@@ -280,6 +370,12 @@ bool IbcHashMap::ibcHashMatch(const Area& lumaArea, std::vector<Position>& cand,
     for (SizeType x = 0; x < lumaArea.width && minSize > 1; x += MIN_PU_SIZE)
     {
       unsigned int hash = m_pos2Hash[lumaArea.pos().y + y][lumaArea.pos().x + x];
+#if TEST_3_2
+      if (rribcFlipType)
+      {
+        hash = pos2HashCurPU[y][x];
+      }
+#endif
       if (m_hash2Pos[hash].size() < minSize)
       {
         minSize = m_hash2Pos[hash].size();
@@ -291,7 +387,7 @@ bool IbcHashMap::ibcHashMatch(const Area& lumaArea, std::vector<Position>& cand,
 
   if (m_hash2Pos[targetHashOneBlock].size() > 1)
   {
-    std::vector<Position>& candOneBlock = m_hash2Pos[targetHashOneBlock];
+    std::vector<Position> &candOneBlock = m_hash2Pos[targetHashOneBlock];
 
     // check whether whole block match
     for (std::vector<Position>::iterator refBlockPos = candOneBlock.begin(); refBlockPos != candOneBlock.end(); refBlockPos++)
@@ -310,6 +406,13 @@ bool IbcHashMap::ibcHashMatch(const Area& lumaArea, std::vector<Position>& cand,
           for (SizeType x = 0; x < lumaArea.width && wholeBlockMatch; x += MIN_PU_SIZE)
           {
             // whether the reference block and current block has the same hash
+#if TEST_3_2
+            if (rribcFlipType)
+            {
+              wholeBlockMatch &= (pos2HashCurPU[y][x] == m_pos2Hash[topLeft.y + y][topLeft.x + x]);
+            }
+            else
+#endif
             wholeBlockMatch &= (m_pos2Hash[lumaArea.pos().y + y][lumaArea.pos().x + x] == m_pos2Hash[topLeft.y + y][topLeft.x + x]);
           }
         }
diff --git a/source/Lib/CommonLib/IbcHashMap.h b/source/Lib/CommonLib/IbcHashMap.h
index 84d57541..fc6e3032 100644
--- a/source/Lib/CommonLib/IbcHashMap.h
+++ b/source/Lib/CommonLib/IbcHashMap.h
@@ -78,8 +78,14 @@ public:
 
   void    init(const int picWidth, const int picHeight);
   void    destroy();
+#if TEST_3_2
+  void rebuildPicHashMap(const PelUnitBuf &pic, bool isDualTree);
+  void buildFlipHashTable(PredictionUnit &pu, unsigned int pos2HashCurPU[MAX_CU_SIZE][MAX_CU_SIZE], const int rribcFlipType);
+  bool ibcHashMatch(PredictionUnit &pu, const Area &lumaArea, std::vector<Position> &cand, const CodingStructure &cs, const int maxCand, const int searchRange4SmallBlk, const int rribcFlipType);
+#else
   void    rebuildPicHashMap(const PelUnitBuf& pic);
   bool    ibcHashMatch(const Area& lumaArea, std::vector<Position>& cand, const CodingStructure& cs, const int maxCand, const int searchRange4SmallBlk);
+#endif
   int     getHashHitRatio(const Area& lumaArea);
 
   int     calHashBlkMatchPerc(const Area& lumaArea);
diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp
index ecd023c5..c50e774d 100644
--- a/source/Lib/CommonLib/InterPrediction.cpp
+++ b/source/Lib/CommonLib/InterPrediction.cpp
@@ -7110,6 +7110,9 @@ void  InterPrediction::updateIBCCandInfo(PredictionUnit &pu, MergeCtx& mrgCtx, u
     mrgCtxTmp.useAltHpelIf[ui] = false;
 #if INTER_LIC
     mrgCtxTmp.LICFlags[ui] = false;
+#endif
+#if TEST_3_2
+    mrgCtxTmp.rribcFlipTypes[ui] = 0;
 #endif
   }
   for (uint32_t uiMergeCand = ((mrgCandIdx < 0) ? 0 : (mrgCandIdx / ADAPTIVE_IBC_SUB_GROUP_SIZE)*ADAPTIVE_IBC_SUB_GROUP_SIZE); uiMergeCand < (((mrgCandIdx < 0) || ((mrgCandIdx / ADAPTIVE_IBC_SUB_GROUP_SIZE + 1)*ADAPTIVE_IBC_SUB_GROUP_SIZE > mrgCtx.numValidMergeCand)) ? mrgCtx.numValidMergeCand : ((mrgCandIdx / ADAPTIVE_IBC_SUB_GROUP_SIZE + 1)*ADAPTIVE_IBC_SUB_GROUP_SIZE)); ++uiMergeCand)
@@ -7132,6 +7135,9 @@ void  InterPrediction::updateIBCCandInfo(PredictionUnit &pu, MergeCtx& mrgCtx, u
     mrgCtxTmp.useAltHpelIf[uiMergeCand] = mrgCtx.useAltHpelIf[uiMergeCand];
 #if INTER_LIC 
     mrgCtxTmp.LICFlags[uiMergeCand] = mrgCtx.LICFlags[uiMergeCand];
+#endif
+#if TEST_3_2
+    mrgCtxTmp.rribcFlipTypes[uiMergeCand] = mrgCtx.rribcFlipTypes[uiMergeCand];
 #endif
   }
   //update
@@ -7155,6 +7161,9 @@ void  InterPrediction::updateIBCCandInfo(PredictionUnit &pu, MergeCtx& mrgCtx, u
     mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtxTmp.useAltHpelIf[RdCandList[uiMergeCand / ADAPTIVE_IBC_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_IBC_SUB_GROUP_SIZE]];
 #if INTER_LIC
     mrgCtx.LICFlags[uiMergeCand] = mrgCtxTmp.LICFlags[RdCandList[uiMergeCand / ADAPTIVE_IBC_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_IBC_SUB_GROUP_SIZE]];
+#endif
+#if TEST_3_2
+    mrgCtx.rribcFlipTypes[uiMergeCand] = mrgCtxTmp.rribcFlipTypes[RdCandList[uiMergeCand / ADAPTIVE_IBC_SUB_GROUP_SIZE][uiMergeCand % ADAPTIVE_IBC_SUB_GROUP_SIZE]];
 #endif
   }
 }
@@ -7182,12 +7191,6 @@ bool InterPrediction::xAMLIBCGetCurBlkTemplate(PredictionUnit& pu, int nCurBlkWi
       for (int l = 0; l < AML_MERGE_TEMPLATE_SIZE; l++)
       {
         int recVal = rec[k + l * recBuf.stride];
-
-        //if (m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
-        //{
-        //  recVal = invLUT[recVal];
-        //}
-
         pcY[k + l * nCurBlkWidth] = recVal;
       }
     }
@@ -7203,12 +7206,6 @@ bool InterPrediction::xAMLIBCGetCurBlkTemplate(PredictionUnit& pu, int nCurBlkWi
       for (int l = 0; l < AML_MERGE_TEMPLATE_SIZE; l++)
       {
         int recVal = rec[recBuf.stride * k + l];
-
-        //if (m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
-        //{
-        //  recVal = invLUT[recVal];
-        //}
-
         pcY[AML_MERGE_TEMPLATE_SIZE * k + l] = recVal;
       }
     }
@@ -7229,11 +7226,27 @@ void InterPrediction::getIBCAMLRefTemplate(PredictionUnit &pu, int nCurBlkWidth,
   if (m_bAMLTemplateAvailabe[0])
   {
     Mv mvTop(0, -AML_MERGE_TEMPLATE_SIZE);
+#if TEST_3_2
+    if (pu.cu->rribcFlipType == 2)
+    {
+      mvTop.setVer(nCurBlkHeight);
+    }
+#endif
     mvTop += mvCurr;
 
     MotionInfo miTop;
     miTop.mv[0] = Mv(mvTop.hor <<horShift , mvTop.ver<< verShift);
     miTop.refIdx[0] = MAX_NUM_REF;
+#if TEST_3_2
+    if (pu.cu->rribcFlipType == 2)
+    {
+      if (!PU::checkIsIBCCandidateValid(pu, miTop, true, true))
+      {
+        mvTop.setVer(mvCurr.getVer() + nCurBlkHeight - 1);
+      }
+    }
+    else
+#endif
     if (!PU::checkIsIBCCandidateValid(pu, miTop))
     {
       mvTop = mvCurr;
@@ -7245,13 +7258,23 @@ void InterPrediction::getIBCAMLRefTemplate(PredictionUnit &pu, int nCurBlkWidth,
     {
       for (int l = 0; l < AML_MERGE_TEMPLATE_SIZE; l++)
       {
+#if TEST_3_2
+        int recVal;
+        if (pu.cu->rribcFlipType == 0)
+        {
+           recVal = rec[k + l * recBuf.stride];
+        }
+        else if (pu.cu->rribcFlipType == 1)
+        {
+          recVal = rec[nCurBlkWidth - 1 - k + l * recBuf.stride];
+        }
+        else
+        {
+          recVal = rec[k + (AML_MERGE_TEMPLATE_SIZE - 1 - l) * recBuf.stride];
+        }
+#else
         int recVal = rec[k + l * recBuf.stride];
-
-        //if (m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
-        //{
-        //  recVal = invLUT[recVal];
-        //}
-
+#endif
         pcY[k + l * nCurBlkWidth] = recVal;
       }
     }
@@ -7260,11 +7283,27 @@ void InterPrediction::getIBCAMLRefTemplate(PredictionUnit &pu, int nCurBlkWidth,
   if (m_bAMLTemplateAvailabe[1])
   {
     Mv mvLeft(-AML_MERGE_TEMPLATE_SIZE, 0);
+#if TEST_3_2
+    if (pu.cu->rribcFlipType == 1)
+    {
+      mvLeft.setHor(nCurBlkWidth);
+    }
+#endif
     mvLeft += mvCurr;
 
     MotionInfo miLeft;
     miLeft.mv[0] = Mv(mvLeft.hor <<horShift , mvLeft.ver<< verShift);
     miLeft.refIdx[0] = MAX_NUM_REF;
+#if TEST_3_2
+    if (pu.cu->rribcFlipType == 1)
+    {
+      if (!PU::checkIsIBCCandidateValid(pu, miLeft, true, false))
+      {
+         mvLeft.setHor(mvCurr.getHor() + nCurBlkWidth - 1);
+      }
+    }
+    else
+#endif
     if (!PU::checkIsIBCCandidateValid(pu, miLeft))
     {
       mvLeft = mvCurr;
@@ -7276,19 +7315,30 @@ void InterPrediction::getIBCAMLRefTemplate(PredictionUnit &pu, int nCurBlkWidth,
     {
       for (int l = 0; l < AML_MERGE_TEMPLATE_SIZE; l++)
       {
+#if TEST_3_2
+        int recVal;
+        if (pu.cu->rribcFlipType == 0)
+        {
+          recVal = rec[recBuf.stride * k + l];
+        }
+        else if (pu.cu->rribcFlipType == 1) 
+        {
+          recVal = rec[recBuf.stride * k + AML_MERGE_TEMPLATE_SIZE - 1 - l];
+        }
+        else
+        {
+          recVal = rec[recBuf.stride * (nCurBlkHeight - 1 - k) + l];
+        }
+#else
         int recVal = rec[recBuf.stride * k + l];
-
-        //if (m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
-        //{
-        //  recVal = invLUT[recVal];
-        //}
-
+#endif
         pcY[AML_MERGE_TEMPLATE_SIZE * k + l] = recVal;
       }
     }
   }
 }
 #endif
+
 #if JVET_Z0075_IBC_HMVP_ENLARGE
 void  InterPrediction::adjustIBCMergeCandidates(PredictionUnit &pu, MergeCtx& mrgCtx,uint32_t startPos,uint32_t endPos)
 {
@@ -7372,6 +7422,9 @@ void  InterPrediction::updateIBCCandInfo(PredictionUnit &pu, MergeCtx& mrgCtx, u
     mrgCtxTmp.useAltHpelIf[ui] = false;
 #if INTER_LIC
     mrgCtxTmp.LICFlags[ui] = false;
+#endif
+#if TEST_3_2
+    mrgCtxTmp.rribcFlipTypes[ui] = 0;
 #endif
   }
   for (uint32_t uiMergeCand = startPos; uiMergeCand < endPos; ++uiMergeCand)
@@ -7388,6 +7441,9 @@ void  InterPrediction::updateIBCCandInfo(PredictionUnit &pu, MergeCtx& mrgCtx, u
     mrgCtxTmp.useAltHpelIf[uiMergeCand] = mrgCtx.useAltHpelIf[uiMergeCand];
 #if INTER_LIC 
     mrgCtxTmp.LICFlags[uiMergeCand] = mrgCtx.LICFlags[uiMergeCand];
+#endif
+#if TEST_3_2
+    mrgCtxTmp.rribcFlipTypes[uiMergeCand] = mrgCtx.rribcFlipTypes[uiMergeCand];
 #endif
   }
   //update
@@ -7405,6 +7461,9 @@ void  InterPrediction::updateIBCCandInfo(PredictionUnit &pu, MergeCtx& mrgCtx, u
     mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtxTmp.useAltHpelIf[RdCandList[uiMergeCand -startPos]];
 #if INTER_LIC
     mrgCtx.LICFlags[uiMergeCand] = mrgCtxTmp.LICFlags[RdCandList[uiMergeCand -startPos]];
+#endif
+#if TEST_3_2
+    mrgCtx.rribcFlipTypes[uiMergeCand] = mrgCtxTmp.rribcFlipTypes[RdCandList[uiMergeCand -startPos]];
 #endif
   }
 }
diff --git a/source/Lib/CommonLib/IntraPrediction.cpp b/source/Lib/CommonLib/IntraPrediction.cpp
index 30e5663a..00781385 100644
--- a/source/Lib/CommonLib/IntraPrediction.cpp
+++ b/source/Lib/CommonLib/IntraPrediction.cpp
@@ -248,7 +248,6 @@ void IntraPrediction::init(ChromaFormat chromaFormatIDC, const unsigned bitDepth
 #endif
 #if JVET_V0130_INTRA_TMP
   unsigned int blkSize;
-
   if( m_pppTarPatch == NULL )
   {
     m_pppTarPatch = new Pel * *[USE_MORE_BLOCKSIZE_DEPTH_MAX];
@@ -6440,6 +6439,7 @@ void IntraPrediction::candidateSearchIntra( CodingUnit* pcCU, unsigned int uiBlk
   unsigned int uiPatchWidth = uiBlkWidth + TMP_TEMPLATE_SIZE;
   unsigned int uiPatchHeight = uiBlkHeight + TMP_TEMPLATE_SIZE;
   unsigned int uiTarDepth = floorLog2( std::max( uiBlkWidth, uiBlkHeight ) ) - 2;
+
   Pel** tarPatch = getTargetPatch( uiTarDepth );
   //Initialize the library for saving the best candidates
   m_tempLibFast.initTemplateDiff( uiPatchWidth, uiPatchHeight, uiBlkWidth, uiBlkHeight, channelBitDepth );
diff --git a/source/Lib/CommonLib/MotionInfo.h b/source/Lib/CommonLib/MotionInfo.h
index 699d6f1c..b31d98a1 100644
--- a/source/Lib/CommonLib/MotionInfo.h
+++ b/source/Lib/CommonLib/MotionInfo.h
@@ -167,6 +167,10 @@ struct MotionInfo
 #if INTER_LIC
   bool     usesLIC;
 #endif
+#if TEST_3_2
+  int  rribcFlipType;
+  Position centerPos;
+#endif
 #if MULTI_HYP_PRED  
   MultiHypVec addHypData;
 #endif
diff --git a/source/Lib/CommonLib/RdCost.h b/source/Lib/CommonLib/RdCost.h
index d5325ff5..1cc504f1 100644
--- a/source/Lib/CommonLib/RdCost.h
+++ b/source/Lib/CommonLib/RdCost.h
@@ -155,14 +155,18 @@ private:
 
   // for motion cost
   Mv                      m_mvPredictor;
+#if TEST_3_2
+  Mv                      m_bvPredictors[3][2];
+#else
   Mv                      m_bvPredictors[2];
+#endif
   double                  m_motionLambda;
   int                     m_iCostScale;
-
   double                  m_dCost; // for ibc
 #if JVET_Z0131_IBC_BVD_BINARIZATION
   EstBvdBitsStruct        m_cBvdBitCosts;
 #endif
+
 public:
   RdCost();
   virtual ~RdCost();
@@ -221,6 +225,224 @@ public:
   // for ibc
   void           getMotionCost(int add) { m_dCost = m_dLambdaMotionSAD + add; }
 
+
+#if TEST_3_2
+  void setPredictors(Mv pcMv[3][2])
+  {
+    for (int j = 0; j < 3; j++)
+    {
+      for (int i = 0; i < 2; i++)
+      {
+        m_bvPredictors[j][i] = pcMv[j][i];
+      }
+    }
+  }
+#if JVET_Z0131_IBC_BVD_BINARIZATION
+  EstBvdBitsStruct *getBvdBitCosts() { return &m_cBvdBitCosts; }
+  inline Distortion getBvCostMultiplePreds(int x, int y, bool useIMV, int rribc_flip_type, uint8_t *bvImvResBest = NULL, int *bvpIdxBest = NULL, bool flag = false, AMVPInfo *amvpInfo4Pel = NULL)
+  {
+    uint32_t b0 = (rribc_flip_type == 1) ? 0 : xGetExpGolombNumberOfBitsIBCV(y - m_bvPredictors[rribc_flip_type][0].getVer());
+    b0 += (rribc_flip_type == 2) ? 0 : xGetExpGolombNumberOfBitsIBCH(x - m_bvPredictors[rribc_flip_type][0].getHor());
+    b0 += m_cBvdBitCosts.bitsIdx[0];
+
+    uint32_t b1 = (rribc_flip_type == 1) ? 0 : xGetExpGolombNumberOfBitsIBCV(y - m_bvPredictors[rribc_flip_type][1].getVer());
+    b1 += (rribc_flip_type == 2) ? 0 : xGetExpGolombNumberOfBitsIBCH(x - m_bvPredictors[rribc_flip_type][1].getHor());
+    b1 += m_cBvdBitCosts.bitsIdx[1];
+
+    if (useIMV)
+    {
+      if (rribc_flip_type == 0)
+      {
+        b0 += (x != m_bvPredictors[rribc_flip_type][0].getHor() || y != m_bvPredictors[rribc_flip_type][0].getVer()) ? m_cBvdBitCosts.bitsImv[0] : 0;
+        b1 += (x != m_bvPredictors[rribc_flip_type][1].getHor() || y != m_bvPredictors[rribc_flip_type][1].getVer()) ? m_cBvdBitCosts.bitsImv[0] : 0;
+      }
+      else if (rribc_flip_type == 1)
+      {
+        b0 += (x != m_bvPredictors[rribc_flip_type][0].getHor()) ? m_cBvdBitCosts.bitsImv[0] : 0;
+        b1 += (x != m_bvPredictors[rribc_flip_type][1].getHor()) ? m_cBvdBitCosts.bitsImv[0] : 0;
+      }
+      else
+      {
+        b0 += (y != m_bvPredictors[rribc_flip_type][0].getVer()) ? m_cBvdBitCosts.bitsImv[0] : 0;
+        b1 += (y != m_bvPredictors[rribc_flip_type][1].getVer()) ? m_cBvdBitCosts.bitsImv[0] : 0;
+      }
+    }
+    uint32_t bBest    = (b1 < b0) ? b1 : b0;
+    int      bBestIdx = (b1 < b0) ? 1 : 0;
+    uint8_t  bestRes;
+    if (rribc_flip_type == 0)
+    {
+      bestRes = (useIMV && (x != m_bvPredictors[rribc_flip_type][bBestIdx].getHor() || y != m_bvPredictors[rribc_flip_type][bBestIdx].getVer())) ? 1 : 0;
+    }
+    else if (rribc_flip_type == 1)
+    {
+      bestRes = (useIMV && (x != m_bvPredictors[rribc_flip_type][bBestIdx].getHor())) ? 1 : 0;
+    }
+    else
+    {
+      bestRes = (useIMV && (y != m_bvPredictors[rribc_flip_type][bBestIdx].getVer())) ? 1 : 0;
+    }
+
+    if (bvImvResBest)
+    {
+      *bvImvResBest = bestRes;
+      *bvpIdxBest   = bBestIdx;
+    }
+
+    if (bestRes && x % 4 == 0 && y % 4 == 0)
+    {
+      Mv cMv(x >> 2, y >> 2);
+
+      Mv tmpBv0;
+      Mv tmpBv1;
+      if (flag)
+      {
+        tmpBv0 = amvpInfo4Pel->mvCand[0];
+        tmpBv1 = amvpInfo4Pel->mvCand[1];
+        tmpBv0.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_4PEL);
+        tmpBv1.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_4PEL);
+      }
+      else
+      {
+        tmpBv0 = m_bvPredictors[rribc_flip_type][0];
+        tmpBv1 = m_bvPredictors[rribc_flip_type][1];
+        tmpBv0.changePrecision(MV_PRECISION_INT, MV_PRECISION_4PEL);
+        tmpBv1.changePrecision(MV_PRECISION_INT, MV_PRECISION_4PEL);
+      }
+
+      uint32_t bQ0, bQ1;
+      if (rribc_flip_type == 0)
+      {
+        bQ0 = (cMv == tmpBv0) ? std::numeric_limits<uint32_t>::max() : (xGetExpGolombNumberOfBitsIBCH(cMv.getHor() - tmpBv0.getHor()) + xGetExpGolombNumberOfBitsIBCV(cMv.getVer() - tmpBv0.getVer()) + m_cBvdBitCosts.bitsIdx[0]);
+        bQ1 = (cMv == tmpBv1) ? std::numeric_limits<uint32_t>::max() : (xGetExpGolombNumberOfBitsIBCH(cMv.getHor() - tmpBv1.getHor()) + xGetExpGolombNumberOfBitsIBCV(cMv.getVer() - tmpBv1.getVer()) + m_cBvdBitCosts.bitsIdx[1]);
+      }
+      else if (rribc_flip_type == 1)
+      {
+        bQ0 = (cMv.getHor() == tmpBv0.getHor()) ? std::numeric_limits<uint32_t>::max() : (xGetExpGolombNumberOfBitsIBCH(cMv.getHor() - tmpBv0.getHor()) + m_cBvdBitCosts.bitsIdx[0]);
+        bQ1 = (cMv.getHor() == tmpBv1.getHor()) ? std::numeric_limits<uint32_t>::max() : (xGetExpGolombNumberOfBitsIBCH(cMv.getHor() - tmpBv1.getHor()) + m_cBvdBitCosts.bitsIdx[1]);
+      }
+      else
+      {
+        bQ0 = (cMv.getVer() == tmpBv0.getVer()) ? std::numeric_limits<uint32_t>::max() : (xGetExpGolombNumberOfBitsIBCV(cMv.getVer() - tmpBv0.getVer()) + m_cBvdBitCosts.bitsIdx[0]);
+        bQ1 = (cMv.getVer() == tmpBv1.getVer()) ? std::numeric_limits<uint32_t>::max() : (xGetExpGolombNumberOfBitsIBCV(cMv.getVer() - tmpBv1.getVer()) + m_cBvdBitCosts.bitsIdx[1]);
+      }
+
+      uint32_t bQBest = (bQ1 < bQ0) ? bQ1 : bQ0;
+      bQBest += (bQBest < std::numeric_limits<uint32_t>::max()) ? m_cBvdBitCosts.bitsImv[1] : 0;
+
+      if (bQBest < bBest)
+      {
+        if (bvImvResBest)
+        {
+          *bvImvResBest = 2;
+          *bvpIdxBest   = (bQ1 < bQ0) ? 1 : 0;
+        }
+        bBest = bQBest;
+      }
+    }
+    return Distortion(m_dCost * bBest) >> SCALE_BITS;
+  }
+#else
+  inline Distortion getBvCostMultiplePreds(int x, int y, bool useIMV, int rribc_flip_type)
+  {
+    return Distortion(m_dCost * getBitsMultiplePreds(x, y, useIMV, rribc_flip_type));
+  }
+  unsigned int getBitsMultiplePreds(int x, int y, bool useIMV, int rribc_flip_type)
+  {
+    int rmvH[2];
+    int rmvV[2];
+    rmvH[0] = x - m_bvPredictors[rribc_flip_type][0].getHor();
+    rmvH[1] = x - m_bvPredictors[rribc_flip_type][1].getHor();
+
+    rmvV[0] = y - m_bvPredictors[rribc_flip_type][0].getVer();
+    rmvV[1] = y - m_bvPredictors[rribc_flip_type][1].getVer();
+
+    int absCand[2];
+    absCand[0] = abs(rmvH[0]) + abs(rmvV[0]);
+    absCand[1] = abs(rmvH[1]) + abs(rmvV[1]);
+
+    int rmvHQP[2];
+    int rmvVQP[2];
+    if (x % 4 == 0 && y % 4 == 0 && useIMV)
+    {
+      int imvShift = 2;
+      int offset   = 1 << (imvShift - 1);
+
+      rmvHQP[0] = (x >> 2) - ((m_bvPredictors[rribc_flip_type][0].getHor() + offset) >> 2);
+      rmvHQP[1] = (x >> 2) - ((m_bvPredictors[rribc_flip_type][1].getHor() + offset) >> 2);
+      rmvVQP[0] = (y >> 2) - ((m_bvPredictors[rribc_flip_type][0].getVer() + offset) >> 2);
+      rmvVQP[1] = (y >> 2) - ((m_bvPredictors[rribc_flip_type][1].getVer() + offset) >> 2);
+
+      int absCandQP[2];
+      absCandQP[0] = abs(rmvHQP[0]) + abs(rmvVQP[0]);
+      absCandQP[1] = abs(rmvHQP[1]) + abs(rmvVQP[1]);
+      unsigned int candBits0QP, candBits1QP;
+      if (absCand[0] < absCand[1])
+      {
+        unsigned int candBits0 = (rribc_flip_type == 1) ? 0 : getIComponentBits(rmvV[0]);
+        candBits0 += (rribc_flip_type == 2) ? 0 : getIComponentBits(rmvH[0]);
+        if (absCandQP[0] < absCandQP[1])
+        {
+          candBits0QP = (rribc_flip_type == 1) ? 0 : getIComponentBits(rmvVQP[0]);
+          candBits0QP += (rribc_flip_type == 2) ? 0 : getIComponentBits(rmvHQP[0]);
+          return candBits0QP < candBits0 ? candBits0QP : candBits0;
+        }
+        else
+        {
+          candBits1QP = (rribc_flip_type == 1) ? 0 : getIComponentBits(rmvVQP[1]);
+          candBits1QP = (rribc_flip_type == 2) ? 0 : getIComponentBits(rmvHQP[1]);
+          return candBits1QP < candBits0 ? candBits1QP : candBits0;
+        }
+      }
+      else
+      {
+        unsigned int candBits1 = (rribc_flip_type == 1) ? 0 : getIComponentBits(rmvV[1]);
+        candBits1 += (rribc_flip_type == 2) ? 0 : getIComponentBits(rmvH[1]);
+        if (absCandQP[0] < absCandQP[1])
+        {
+          candBits0QP = (rribc_flip_type == 1) ? 0 : getIComponentBits(rmvVQP[0]);
+          candBits0QP += (rribc_flip_type == 2) ? 0 : getIComponentBits(rmvHQP[0]);
+          return candBits0QP < candBits1 ? candBits0QP : candBits1;
+        }
+        else
+        {
+          candBits1QP = (rribc_flip_type == 1) ? 0 : getIComponentBits(rmvVQP[1]);
+          candBits1QP = (rribc_flip_type == 2) ? 0 : getIComponentBits(rmvHQP[1]);
+          return candBits1QP < candBits1 ? candBits1QP : candBits1;
+        }
+      }
+    }
+    else
+    {
+      if (absCand[0] < absCand[1])
+      {
+        return (rribc_flip_type == 1) ? getIComponentBits(rmvH[0]) : ((rribc_flip_type == 2) ? getIComponentBits(rmvV[0]) : (getIComponentBits(rmvH[0]) + getIComponentBits(rmvV[0])));
+      }
+      else
+      {
+        return (rribc_flip_type == 1) ? getIComponentBits(rmvH[1]) : ((rribc_flip_type == 2) ? getIComponentBits(rmvV[1]) : (getIComponentBits(rmvH[1]) + getIComponentBits(rmvV[1])));
+      }
+    }
+  }
+
+  unsigned int getIComponentBits(int val)
+  {
+    if (!val)
+      return 1;
+
+    unsigned int length = 1;
+    unsigned int temp   = (val <= 0) ? (-val << 1) + 1 : (val << 1);
+
+    while (1 != temp)
+    {
+      temp >>= 1;
+      length += 2;
+    }
+
+    return length;
+  }
+#endif
+#else
   void    setPredictors(Mv* pcMv)
   {
     for (int i = 0; i<2; i++)
@@ -228,10 +450,11 @@ public:
       m_bvPredictors[i] = pcMv[i];
     }
   }
+
 #if JVET_Z0131_IBC_BVD_BINARIZATION
-  EstBvdBitsStruct*  getBvdBitCosts() 
-  { 
-    return &m_cBvdBitCosts; 
+  EstBvdBitsStruct*  getBvdBitCosts()
+  {
+    return &m_cBvdBitCosts;
   }
 #if JVET_Z0084_IBC_TM
   inline Distortion getBvCostMultiplePreds(int x, int y, bool useIMV, uint8_t *bvImvResBest = NULL, int *bvpIdxBest = NULL, bool flag = false, AMVPInfo* amvpInfo4Pel = NULL)
@@ -262,7 +485,7 @@ public:
 #if JVET_Z0084_IBC_TM
       Mv tmpBv0;
       Mv tmpBv1;
-      if (flag) 
+      if (flag)
       {
         tmpBv0 = amvpInfo4Pel->mvCand[0];
         tmpBv1 = amvpInfo4Pel->mvCand[1];
@@ -395,6 +618,7 @@ public:
     return length;
   }
 #endif
+#endif
 
 #if ENABLE_SPLIT_PARALLELISM
   void copyState( const RdCost& other );
@@ -414,8 +638,19 @@ public:
 
     return uiLength2 + ( floorLog2(uiTemp2) << 1 );
   }
+
   Distortion     getCostOfVectorWithPredictor( const int x, const int y, const unsigned imvShift )  { return Distortion( m_motionLambda * getBitsOfVectorWithPredictor(x, y, imvShift )); }
-  uint32_t           getBitsOfVectorWithPredictor( const int x, const int y, const unsigned imvShift )  { return xGetExpGolombNumberOfBits(((x << m_iCostScale) - m_mvPredictor.getHor())>>imvShift) + xGetExpGolombNumberOfBits(((y << m_iCostScale) - m_mvPredictor.getVer())>>imvShift); }
+#if TEST_3_2 && !JVET_Z0131_IBC_BVD_BINARIZATION
+  uint32_t getBitsOfVectorWithPredictor( const int x, const int y, const unsigned imvShift, const int &rribc_flip_type = 0)
+  {
+    return (rribc_flip_type == 1) ? xGetExpGolombNumberOfBits(((x << m_iCostScale) - m_mvPredictor.getHor()) >> imvShift) : ((rribc_flip_type == 2) ? xGetExpGolombNumberOfBits(((y << m_iCostScale) - m_mvPredictor.getVer()) >> imvShift)
+                  : (xGetExpGolombNumberOfBits(((x << m_iCostScale) - m_mvPredictor.getHor()) >> imvShift) + xGetExpGolombNumberOfBits(((y << m_iCostScale) - m_mvPredictor.getVer()) >> imvShift)));
+  }
+#else
+  uint32_t       getBitsOfVectorWithPredictor( const int x, const int y, const unsigned imvShift )  { return xGetExpGolombNumberOfBits(((x << m_iCostScale) - m_mvPredictor.getHor())>>imvShift) + xGetExpGolombNumberOfBits(((y << m_iCostScale) - m_mvPredictor.getVer())>>imvShift); }
+#endif
+
+
 #if JVET_Z0131_IBC_BVD_BINARIZATION
   // for block vector cost
   uint32_t    xGetExpGolombNumberOfBitsIBCH( int iVal )
@@ -472,6 +707,7 @@ public:
     }
   }
 
+#if !TEST_3_2
   Distortion     getCostOfVectorWithPredictorIBC( const int x, const int y, const unsigned imvShift )  
   { 
     return Distortion( m_motionLambda * getBitsOfVectorWithPredictorIBC(x, y, imvShift )) >> SCALE_BITS; 
@@ -481,6 +717,7 @@ public:
     return xGetExpGolombNumberOfBitsIBCH(((x << m_iCostScale) - m_mvPredictor.getHor())>>imvShift) + xGetExpGolombNumberOfBitsIBCV(((y << m_iCostScale) - m_mvPredictor.getVer())>>imvShift); 
   }
 #endif
+#endif
 #if WCG_EXT
          void    saveUnadjustedLambda       ();
          void    initLumaLevelToWeightTable ();
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 74385032..2fe69114 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -50,6 +50,8 @@
 #include <assert.h>
 #include <cassert>
 
+#define TEST_3_2                                          1
+
 
 #define BASE_ENCODER                                      1
 #define BASE_NORMATIVE                                    1
diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp
index ed605987..d84d5db9 100644
--- a/source/Lib/CommonLib/Unit.cpp
+++ b/source/Lib/CommonLib/Unit.cpp
@@ -320,6 +320,9 @@ CodingUnit& CodingUnit::operator=( const CodingUnit& other )
 #if INTER_LIC
   LICFlag           = other.LICFlag;
 #endif
+#if TEST_3_2
+  rribcFlipType = other.rribcFlipType;
+#endif
 
   for (int idx = 0; idx < MAX_NUM_CHANNEL_TYPE; idx++)
   {
@@ -415,6 +418,9 @@ void CodingUnit::initData()
 #if INTER_LIC
   LICFlag = false;
 #endif
+#if TEST_3_2
+  rribcFlipType = 0;
+#endif
 
   for (int idx = 0; idx < MAX_NUM_CHANNEL_TYPE; idx++)
   {
diff --git a/source/Lib/CommonLib/Unit.h b/source/Lib/CommonLib/Unit.h
index 84551892..2bdf0170 100644
--- a/source/Lib/CommonLib/Unit.h
+++ b/source/Lib/CommonLib/Unit.h
@@ -350,6 +350,9 @@ struct CodingUnit : public UnitArea
 #if INTER_LIC
   bool           LICFlag;
 #endif
+#if TEST_3_2
+  int    rribcFlipType;
+#endif
 
   // needed for fast imv mode decisions
   int8_t          imvNumCand;
diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp
index 90dcbccd..13d9f806 100644
--- a/source/Lib/CommonLib/UnitTools.cpp
+++ b/source/Lib/CommonLib/UnitTools.cpp
@@ -445,6 +445,13 @@ void CU::saveMotionInHMVP( const CodingUnit& cu, const bool isToBeDone )
 #if MULTI_HYP_PRED
     mi.addHypData = pu.addHypData;
 #endif
+#if TEST_3_2
+    if(CU::isIBC(cu))
+    {
+      mi.centerPos.x = cu.lx() + (cu.lwidth() >> 1);
+      mi.centerPos.y = cu.ly() + (cu.lheight() >> 1);
+    }
+#endif
 
     mi.BcwIdx = (mi.interDir == 3) ? cu.BcwIdx : BCW_DEFAULT;
 
@@ -1792,11 +1799,11 @@ bool PU::addMergeHMVPCand(const CodingStructure &cs, MergeCtx &mrgCtx, const int
   const Slice& slice = *cs.slice;
   MotionInfo miNeighbor;
 
-#if JVET_Z0075_IBC_HMVP_ENLARGE
 #if JVET_Z0118_GDR  
   bool isClean = cs.isClean(pu.cu->Y().bottomRight(), CHANNEL_TYPE_LUMA);
 #endif
 
+#if JVET_Z0075_IBC_HMVP_ENLARGE
 #if JVET_Z0118_GDR  
   auto &lut = (isClean) ? cs.motionLut.lut1 : cs.motionLut.lut0;
 #else
@@ -1813,10 +1820,28 @@ bool PU::addMergeHMVPCand(const CodingStructure &cs, MergeCtx &mrgCtx, const int
 
   int num_avai_candInLUT = (int)lut.size();
 
+#if TEST_3_2 && !JVET_Z0075_IBC_HMVP_ENLARGE
+  int cPosCurX = pu.lx() + (pu.lwidth() >> 1);
+  int cPosCurY = pu.ly() + (pu.lheight() >> 1);
+  int thW      = (pu.lwidth() >> 1) * 3;
+  int thH      = (pu.lheight() >> 1) * 3;
+#endif
+
   for (int mrgIdx = 1; mrgIdx <= num_avai_candInLUT; mrgIdx++)
   {
     miNeighbor = lut[num_avai_candInLUT - mrgIdx];
 
+#if TEST_3_2 && !JVET_Z0075_IBC_HMVP_ENLARGE
+    if (ibcFlag)
+    {
+      Position cPos(miNeighbor.centerPos.x, miNeighbor.centerPos.y);
+      if (pu.mergeFlag || ((abs(cPosCurX - (int) cPos.x) <= thW) && (abs(cPosCurY - (int) cPos.y) <= thH)))
+      {
+        rribcAdjustMotion(pu, &cPos, miNeighbor);
+      }
+    }
+#endif
+
 #if JVET_X0083_BM_AMVP_MERGE_MODE
 #if JVET_Y0128_NON_CTC
     bool isValidAmMode = checkIsValidMergeMvCand(pu, miNeighbor.refIdx);
@@ -1853,9 +1878,15 @@ bool PU::addMergeHMVPCand(const CodingStructure &cs, MergeCtx &mrgCtx, const int
       mrgCtx.BcwIdx            [cnt] = (miNeighbor.interDir == 3) ? miNeighbor.BcwIdx : BCW_DEFAULT;
 #if INTER_LIC
       mrgCtx.LICFlags          [cnt] = miNeighbor.usesLIC;
+#if TEST_3_2
+      mrgCtx.rribcFlipTypes    [cnt] = 0;
+#endif
 #if !JVET_Z0075_IBC_HMVP_ENLARGE
       if (ibcFlag)
       {
+#if TEST_3_2
+        mrgCtx.rribcFlipTypes[cnt] = !pu.tmMergeFlag ? miNeighbor.rribcFlipType : 0;
+#endif
         CHECK(mrgCtx.LICFlags[cnt], "addMergeHMVPCand: LIC is not used with IBC mode")
       }
 #endif
@@ -1958,15 +1989,31 @@ bool PU::addIBCMergeHMVPCand(const CodingStructure &cs, MergeCtx &mrgCtx, const
   int num_avai_candInLUT = (int)lut.size();
   int compareNum = cnt;
 
+#if TEST_3_2
+  int cPosCurX = pu.lx() + (pu.lwidth() >> 1);
+  int cPosCurY = pu.ly() + (pu.lheight() >> 1);
+  int thW      = (pu.lwidth() >> 1) * 3;
+  int thH      = (pu.lheight() >> 1) * 3;
+#endif
   for (int mrgIdx = 1; mrgIdx <= num_avai_candInLUT; mrgIdx++)
   {
     miNeighbor = lut[num_avai_candInLUT - mrgIdx];
+#if TEST_3_2
+    Position cPos(miNeighbor.centerPos.x, miNeighbor.centerPos.y);
+    if (pu.mergeFlag || ((abs(cPosCurX - (int) cPos.x) <= thW) && (abs(cPosCurY - (int) cPos.y) <= thH)))
+    {
+      rribcAdjustMotion(pu, &cPos, miNeighbor);
+    }
+#endif
 
 #if JVET_Y0058_IBC_LIST_MODIFY && JVET_Z0084_IBC_TM
     if (checkIsIBCCandidateValid(pu, miNeighbor))
     {
 #endif
       mrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir;
+#if TEST_3_2
+      mrgCtx.rribcFlipTypes[cnt] = !pu.tmMergeFlag ? miNeighbor.rribcFlipType : 0;
+#endif
 #if !JVET_Z0084_IBC_TM
       mrgCtx.useAltHpelIf      [cnt] = false;
       mrgCtx.BcwIdx            [cnt] = (miNeighbor.interDir == 3) ? miNeighbor.BcwIdx : BCW_DEFAULT;
@@ -2033,6 +2080,50 @@ bool PU::addIBCMergeHMVPCand(const CodingStructure &cs, MergeCtx &mrgCtx, const
   return false;
 }
 #endif
+
+#if TEST_3_2
+void PU::rribcAdjustMotion(const PredictionUnit &pu, const Position *cPos, MotionInfo &miNeighbor)
+{
+  if (pu.tmMergeFlag)
+  {
+    return;
+  }
+
+  int curCPosX = pu.lx() + (pu.lwidth() >> 1);
+  int curCPosY = pu.ly() + (pu.lheight() >> 1);
+
+  if (miNeighbor.isIBCmot && miNeighbor.rribcFlipType && (pu.mergeFlag || (!pu.mergeFlag && (pu.cu->rribcFlipType == miNeighbor.rribcFlipType))))
+  {
+    if (miNeighbor.rribcFlipType == 1)
+    {
+      int shift = (cPos->x - curCPosX) << 1;
+      if (shift)
+      {
+        int storeHor = miNeighbor.mv[0].getHor();
+        miNeighbor.mv[0].setHor(storeHor + (shift << 4));
+        if (!checkIsIBCCandidateValid(pu, miNeighbor))
+        {
+          miNeighbor.mv[0].setHor(storeHor);
+        }
+      }
+    }
+    else if (miNeighbor.rribcFlipType == 2)
+    {
+      int shift = (cPos->y - curCPosY) << 1;
+      if (shift)
+      {
+        int storeVer = miNeighbor.mv[0].getVer();
+        miNeighbor.mv[0].setVer(storeVer + (shift << 4));
+        if (!checkIsIBCCandidateValid(pu, miNeighbor))
+        {
+          miNeighbor.mv[0].setVer(storeVer);
+        }
+      }
+    }
+  }
+}
+#endif
+
 void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const int& mrgCandIdx)
 {
   const CodingStructure &cs = *pu.cs;
@@ -2043,7 +2134,11 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const
 #endif
 #if JVET_Z0084_IBC_TM
 #if TM_MRG
+#if TEST_3_2
+  const uint32_t mvdSimilarityThresh = ((pu.tmMergeFlag && pu.mergeFlag) || (!pu.mergeFlag && !pu.cu->rribcFlipType)) ? PU::getTMMvdThreshold(pu) : 1;
+#else
   const uint32_t mvdSimilarityThresh = pu.tmMergeFlag ? PU::getTMMvdThreshold(pu) : 1;
+#endif
 #else
   const uint32_t mvdSimilarityThresh = 1;
 #endif
@@ -2058,6 +2153,9 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const
     mrgCtx.useAltHpelIf[ui] = false;
 #if INTER_LIC
     mrgCtx.LICFlags[ui] = false;
+#endif
+#if TEST_3_2
+    mrgCtx.rribcFlipTypes[ui] = 0;
 #endif
   }
 
@@ -2085,6 +2183,10 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const
   if (isGt4x4 && isAvailableA1)
   {
     miLeft = puLeft->getMotionInfo(posLB.offset(-1, 0));
+#if TEST_3_2
+    Position cPos(puLeft->lx() + (puLeft->lwidth() >> 1), puLeft->ly() + (puLeft->lheight() >> 1));
+    rribcAdjustMotion(pu, &cPos, miLeft);
+#endif
 
 #if JVET_Y0058_IBC_LIST_MODIFY
     if (checkIsIBCCandidateValid(pu, miLeft))
@@ -2094,6 +2196,9 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const
     mrgCtx.interDirNeighbours[cnt] = miLeft.interDir;
     // get Mv from Left
     mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miLeft.mv[0], miLeft.refIdx[0]);
+#if TEST_3_2
+    mrgCtx.rribcFlipTypes[cnt] = (miLeft.isIBCmot && !pu.tmMergeFlag) ? miLeft.rribcFlipType : 0;
+#endif
     if (mrgCandIdx == cnt)
     {
       return;
@@ -2116,6 +2221,10 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const
   if (isGt4x4 && isAvailableB1)
   {
     miAbove = puAbove->getMotionInfo(posRT.offset(0, -1));
+#if TEST_3_2
+    Position cPos(puAbove->lx() + (puAbove->lwidth() >> 1), puAbove->ly() + (puAbove->lheight() >> 1));
+    rribcAdjustMotion(pu, &cPos, miAbove);
+#endif
 
     if (!isAvailableA1 || (miAbove != miLeft))
     {
@@ -2127,6 +2236,9 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const
       mrgCtx.interDirNeighbours[cnt] = miAbove.interDir;
       // get Mv from Above
       mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAbove.mv[0], miAbove.refIdx[0]);
+#if TEST_3_2
+      mrgCtx.rribcFlipTypes[cnt] = (miAbove.isIBCmot && !pu.tmMergeFlag) ? miAbove.rribcFlipType : 0;
+#endif
 
 #if JVET_Z0084_IBC_TM
       if( !mrgCtx.xCheckSimilarIBCMotion(cnt, mvdSimilarityThresh) )
@@ -2157,6 +2269,10 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const
   if (isGt4x4 && isAvailableB0)
   {
     miAboveRight = puAboveRight->getMotionInfo(posRT.offset(1, -1));
+#if TEST_3_2
+    Position cPos(puAboveRight->lx() + (puAboveRight->lwidth() >> 1), puAboveRight->ly() + (puAboveRight->lheight() >> 1));
+    rribcAdjustMotion(pu, &cPos, miAboveRight);
+#endif
 
     if ((!isAvailableB1 || (miAbove != miAboveRight)) && (!isAvailableA1 || (miLeft != miAboveRight)))
     {
@@ -2166,6 +2282,9 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const
         mrgCtx.interDirNeighbours[cnt] = miAboveRight.interDir;
         // get Mv from Above-right
         mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAboveRight.mv[0], miAboveRight.refIdx[0]);
+#if TEST_3_2
+        mrgCtx.rribcFlipTypes[cnt] = (miAboveRight.isIBCmot && !pu.tmMergeFlag) ? miAboveRight.rribcFlipType : 0;
+#endif
 
 #if JVET_Z0084_IBC_TM
         if( !mrgCtx.xCheckSimilarIBCMotion(cnt, mvdSimilarityThresh) )
@@ -2193,6 +2312,10 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const
   if (isGt4x4 && isAvailableA0)
   {
     miBelowLeft = puLeftBottom->getMotionInfo(posLB.offset(-1, 1));
+#if TEST_3_2
+    Position cPos(puLeftBottom->lx() + (puLeftBottom->lwidth() >> 1), puLeftBottom->ly() + (puLeftBottom->lheight() >> 1));
+    rribcAdjustMotion(pu, &cPos, miBelowLeft);
+#endif
 
     if ((!isAvailableA1 || (miBelowLeft != miLeft)) && (!isAvailableB1 || (miBelowLeft != miAbove)) && (!isAvailableB0 || (miBelowLeft != miAboveRight)))
     {
@@ -2201,6 +2324,9 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const
         // get Inter Dir
         mrgCtx.interDirNeighbours[cnt] = miBelowLeft.interDir;
         mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miBelowLeft.mv[0], miBelowLeft.refIdx[0]);
+#if TEST_3_2
+        mrgCtx.rribcFlipTypes[cnt] = (miBelowLeft.isIBCmot && !pu.tmMergeFlag) ? miBelowLeft.rribcFlipType : 0;
+#endif
 
 #if JVET_Z0084_IBC_TM
         if( !mrgCtx.xCheckSimilarIBCMotion(cnt, mvdSimilarityThresh) )
@@ -2234,6 +2360,10 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const
     if (isGt4x4 && isAvailableB2)
     {
       miAboveLeft = puAboveLeft->getMotionInfo(posLT.offset(-1, -1));
+#if TEST_3_2
+      Position cPos(puAboveLeft->lx() + (puAboveLeft->lwidth() >> 1), puAboveLeft->ly() + (puAboveLeft->lheight() >> 1));
+      rribcAdjustMotion(pu, &cPos, miAboveLeft);
+#endif
 
       if ((!isAvailableA1 || (miLeft != miAboveLeft)) && (!isAvailableB1 || (miAbove != miAboveLeft)) && (!isAvailableA0 || (miBelowLeft != miAboveLeft)) && (!isAvailableB0 || (miAboveRight != miAboveLeft)))
       {
@@ -2242,6 +2372,9 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const
           // get Inter Dir
           mrgCtx.interDirNeighbours[cnt] = miAboveLeft.interDir;
           mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAboveLeft.mv[0], miAboveLeft.refIdx[0]);
+#if TEST_3_2
+        mrgCtx.rribcFlipTypes[cnt] = (miAboveLeft.isIBCmot && !pu.tmMergeFlag) ? miAboveLeft.rribcFlipType : 0;
+#endif
 
 #if JVET_Z0084_IBC_TM
           if( !mrgCtx.xCheckSimilarIBCMotion(cnt, mvdSimilarityThresh) )
@@ -2436,6 +2569,9 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const
     miCand.mv[0] = mvp;
     mrgCtx.mvFieldNeighbours[cnt * 2].setMvField(mvp, MAX_NUM_REF);
     mrgCtx.interDirNeighbours[cnt] = 1;
+#if TEST_3_2
+    mrgCtx.rribcFlipTypes[cnt] = 0;
+#endif
 
 #if JVET_Z0084_IBC_TM
     if (!mrgCtx.xCheckSimilarIBCMotion(cnt, mvdSimilarityThresh) && checkIsIBCCandidateValid(pu, miCand))
@@ -2457,6 +2593,9 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const
   {
     mrgCtx.interDirNeighbours[cnt] = 1;
     mrgCtx.mvFieldNeighbours[cnt * 2].setMvField(Mv(0, 0), MAX_NUM_REF);
+#if TEST_3_2
+    mrgCtx.rribcFlipTypes[cnt] = 0;
+#endif
     if (mrgCandIdx == cnt)
     {
       return;
@@ -2482,14 +2621,23 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const
 }
 
 #if  JVET_Y0058_IBC_LIST_MODIFY
+#if TEST_3_2
+bool PU::checkIsIBCCandidateValid(const PredictionUnit& pu, const MotionInfo miNeighbor, bool isRefTemplate, bool isRefAbove)
+#else
 bool PU::checkIsIBCCandidateValid(const PredictionUnit& pu, const MotionInfo miNeighbor)
+#endif
 {
   Mv bv = miNeighbor.mv[REF_PIC_LIST_0];
   bv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT); // used for only integer resolution
   const int cuPelX = pu.Y().x;
   const int cuPelY = pu.Y().y;
+#if TEST_3_2
+  int roiWidth  = (isRefTemplate && !isRefAbove) ? AML_MERGE_TEMPLATE_SIZE : pu.lwidth();
+  int roiHeight = (isRefTemplate && isRefAbove) ? AML_MERGE_TEMPLATE_SIZE : pu.lheight();
+#else
   int roiWidth = pu.lwidth();
   int roiHeight = pu.lheight();
+#endif
   const int picWidth = pu.cs->slice->getPPS()->getPicWidthInLumaSamples();
   const int picHeight = pu.cs->slice->getPPS()->getPicHeightInLumaSamples();
   const unsigned int  lcuWidth = pu.cs->slice->getSPS()->getMaxCUWidth();
@@ -2769,6 +2917,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
     mrgCtx.BcwIdx[ui] = BCW_DEFAULT;
 #if INTER_LIC
     mrgCtx.LICFlags[ui] = false;
+#endif
+#if TEST_3_2
+    mrgCtx.rribcFlipTypes[ui] = 0;
 #endif
     mrgCtx.interDirNeighbours[ui] = 0;
     mrgCtx.mvFieldNeighbours[(ui << 1)    ].refIdx = NOT_VALID;
@@ -6043,9 +6194,16 @@ void PU::fillIBCMvpCand(PredictionUnit &pu, AMVPInfo &amvpInfo)
 
   MergeCtx mergeCtx;
 #if JVET_Z0084_IBC_TM && TM_AMVP
+#if TEST_3_2
+  pInfo->maxSimilarityThreshold = (pu.cs->sps->getUseDMVDMode() && pcInter && !pu.cu->rribcFlipType) ? PU::getTMMvdThreshold(pu) : 1;
+  if (!pu.cu->rribcFlipType)
+  {
+   pu.tmMergeFlag = true;
+  }
+#else
   pInfo->maxSimilarityThreshold = (pu.cs->sps->getUseDMVDMode() && pcInter) ? PU::getTMMvdThreshold(pu) : 1;
-
   pu.tmMergeFlag = true;
+#endif
 #if JVET_Z0075_IBC_HMVP_ENLARGE
   PU::getIBCMergeCandidates(pu, mergeCtx, pu.cs->sps->getMaxNumIBCMergeCand());
 #else
@@ -6065,7 +6223,11 @@ void PU::fillIBCMvpCand(PredictionUnit &pu, AMVPInfo &amvpInfo)
     candIdx++;
   }
 
+#if TEST_3_2
+  if (pu.cs->sps->getUseDMVDMode() && pcInter && pInfo->numCand > 0 && !pu.cu->rribcFlipType)
+#else
   if (pu.cs->sps->getUseDMVDMode() && pcInter && pInfo->numCand > 0)
+#endif
   {
     struct AMVPSort
     {
@@ -10070,6 +10232,9 @@ void PU::spanMotionInfo( PredictionUnit &pu, const MergeCtx &mrgCtx )
 #if INTER_LIC
     mi.usesLIC = pu.cu->LICFlag;
 #endif
+#if TEST_3_2
+    mi.rribcFlipType = mi.isIBCmot ? pu.cu->rribcFlipType : 0;
+#endif
 
     if( mi.isInter )
     {
@@ -10533,6 +10698,16 @@ void PU::applyImv( PredictionUnit& pu, MergeCtx &mrgCtx, InterPrediction *interP
 #endif
       pu.mv    [0] = amvpInfo.mvCand[mvpIdx] + pu.mvd[0];
       pu.mv[0].mvCliptoStorageBitDepth();
+#if TEST_3_2
+      if (CU::isIBC(*pu.cu) && pu.cu->rribcFlipType == 1)
+      {
+        pu.mv[0].setVer(0);
+      }
+      else if (CU::isIBC(*pu.cu) && pu.cu->rribcFlipType == 2)
+      {
+        pu.mv[0].setHor(0);
+      }
+#endif
 #if JVET_Z0160_IBC_ZERO_PADDING
       pu.bv = pu.mv[0];
       pu.bv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT);
diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h
index aff0bd88..5e91bb57 100644
--- a/source/Lib/CommonLib/UnitTools.h
+++ b/source/Lib/CommonLib/UnitTools.h
@@ -190,9 +190,16 @@ namespace PU
   void getNonAdjacentMergeCand        (const PredictionUnit &pu, MergeCtx& mvpMrgCtx);
 #endif
   void getIBCMergeCandidates          (const PredictionUnit &pu, MergeCtx& mrgCtx, const int& mrgCandIdx = -1);
+#if TEST_3_2
+  void rribcAdjustMotion(const PredictionUnit &pu, const Position *cPos, MotionInfo &miNeighbor);
+#if  JVET_Y0058_IBC_LIST_MODIFY
+  bool checkIsIBCCandidateValid       (const PredictionUnit &pu,const MotionInfo miNeighbor, bool isRefTemplate = false, bool isRefAbove = false );
+#endif
+#else
 #if  JVET_Y0058_IBC_LIST_MODIFY
   bool checkIsIBCCandidateValid       (const PredictionUnit &pu,const MotionInfo miNeighbor);
 #endif
+#endif
 #if JVET_Y0058_IBC_LIST_MODIFY || JVET_Z0084_IBC_TM
   bool searchBv(const PredictionUnit& pu, int xPos, int yPos, int width, int height, int picWidth, int picHeight, int xBv, int yBv, int ctuSize);
 #endif
diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp
index 81317de4..90409179 100644
--- a/source/Lib/DecoderLib/CABACReader.cpp
+++ b/source/Lib/DecoderLib/CABACReader.cpp
@@ -2972,6 +2972,11 @@ void CABACReader::prediction_unit( PredictionUnit& pu, MergeCtx& mrgCtx )
   {
     merge_flag( pu );
   }
+
+#if TEST_3_2
+  rribc_data(*pu.cu);
+#endif
+
   if( pu.mergeFlag )
   {
     merge_data(pu);
@@ -2989,10 +2994,18 @@ void CABACReader::prediction_unit( PredictionUnit& pu, MergeCtx& mrgCtx )
     pu.cu->affine = false;
     pu.refIdx[REF_PIC_LIST_0] = MAX_NUM_REF;
     RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE(STATS__CABAC_BITS__MVD, pu.lumaSize());
+#if TEST_3_2
+#if JVET_Z0131_IBC_BVD_BINARIZATION
+    bvdCoding(pu.mvd[REF_PIC_LIST_0], pu.cu->rribcFlipType);
+#else
+    mvd_coding(pu.mvd[REF_PIC_LIST_0], true, pu.cu->rribcFlipType);
+#endif
+#else
 #if JVET_Z0131_IBC_BVD_BINARIZATION
     bvdCoding(pu.mvd[REF_PIC_LIST_0]);
 #else
     mvd_coding(pu.mvd[REF_PIC_LIST_0]);
+#endif
 #endif
     if (pu.cs->sps->getMaxNumIBCMergeCand() == 1)
     {
@@ -4668,8 +4681,26 @@ bool CABACReader::cbf_comp( CodingStructure& cs, const CompArea& area, unsigned
 //--------------------------------------------------------------------------------
 //    void  mvd_coding( pu, refList )
 //================================================================================
-
-void CABACReader::mvd_coding( Mv &rMvd 
+#if TEST_3_2
+void CABACReader::mvd_coding( Mv &rMvd
+#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  , bool codeSign
+#endif
+  , const int &rribc_flip_type
+)
+{
+  // abs_mvd_greater0_flag[ 0 | 1 ]
+  int horAbs = 0, verAbs = 0;
+  if (rribc_flip_type != 2)
+  {
+    horAbs = (int) m_BinDecoder.decodeBin(Ctx::Mvd());
+  }
+  if (rribc_flip_type != 1)
+  {
+    verAbs = (int) m_BinDecoder.decodeBin(Ctx::Mvd());
+  }
+#else
+void CABACReader::mvd_coding( Mv &rMvd
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
   , bool codeSign
 #endif
@@ -4678,6 +4709,7 @@ void CABACReader::mvd_coding( Mv &rMvd
   // abs_mvd_greater0_flag[ 0 | 1 ]
   int horAbs = (int)m_BinDecoder.decodeBin(Ctx::Mvd());
   int verAbs = (int)m_BinDecoder.decodeBin(Ctx::Mvd());
+#endif
 
   // abs_mvd_greater1_flag[ 0 | 1 ]
   if (horAbs)
@@ -4751,10 +4783,24 @@ unsigned CABACReader::xReadBvdContext(unsigned ctxT, int offset, int param)
 #endif
 
 #if JVET_Z0131_IBC_BVD_BINARIZATION
+#if TEST_3_2
+void CABACReader::bvdCoding(Mv &rMvd, const int &rribc_flip_type)
+{
+  int horAbs = 0, verAbs = 0;
+  if (rribc_flip_type != 2)
+  {
+    horAbs = (int) m_BinDecoder.decodeBin(Ctx::Bvd(HOR_BVD_CTX_OFFSET));
+  }
+  if (rribc_flip_type != 1)
+  {
+    verAbs = (int) m_BinDecoder.decodeBin(Ctx::Bvd(VER_BVD_CTX_OFFSET));
+  }
+#else
 void CABACReader::bvdCoding( Mv &rMvd )
 {
   int horAbs = (int)m_BinDecoder.decodeBin(Ctx::Bvd(HOR_BVD_CTX_OFFSET));
   int verAbs = (int)m_BinDecoder.decodeBin(Ctx::Bvd(VER_BVD_CTX_OFFSET));
+#endif
 
   if (horAbs)
   {
@@ -6244,6 +6290,27 @@ void CABACReader::cu_lic_flag( CodingUnit& cu )
 }
 #endif
 
+#if TEST_3_2
+void CABACReader::rribc_data(CodingUnit &cu)
+{
+  if (!CU::isIBC(cu) || cu.firstPU->mergeFlag)
+  {
+    return;
+  }
+
+  cu.rribcFlipType = 0;
+
+  unsigned ctxId   = DeriveCtx::CtxRribcFlipType(cu);
+  cu.rribcFlipType = (m_BinDecoder.decodeBin(Ctx::rribcFlipType(ctxId)));
+  if (cu.rribcFlipType)
+  {
+    cu.rribcFlipType += m_BinDecoder.decodeBin(Ctx::rribcFlipType(3));
+  }
+  DTRACE(g_trace_ctx, D_SYNTAX, "rribc_data() rribcFlipType = %d\n", cu.rribcFlipType);
+}
+#endif
+
+
 #if SIGN_PREDICTION
 void CABACReader::parsePredictedSigns( TransformUnit &tu, ComponentID compID )
 {
diff --git a/source/Lib/DecoderLib/CABACReader.h b/source/Lib/DecoderLib/CABACReader.h
index 83d31bd8..44ca1e66 100644
--- a/source/Lib/DecoderLib/CABACReader.h
+++ b/source/Lib/DecoderLib/CABACReader.h
@@ -196,6 +196,17 @@ public:
   bool        cbf_comp                  ( CodingStructure&              cs,     const CompArea& area,     unsigned depth, const bool prevCbf = false, const bool useISP = false );
 
   // mvd coding (clause 7.3.8.9)
+#if TEST_3_2
+#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+   void        mvd_coding                ( Mv &rMvd, bool codeSign = true, const int &rribc_flip_type = 0);
+#else
+   void        mvd_coding                ( Mv &rMvd, const int &rribc_flip_type = 0);
+#endif
+#if JVET_Z0131_IBC_BVD_BINARIZATION
+  void        bvdCoding                ( Mv &rMvd, const int &rribc_flip_type = 0);
+  unsigned    xReadBvdContext(unsigned ctxT, int offset, int param);
+#endif
+#else
   void        mvd_coding                ( Mv &rMvd 
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
     , bool codeSign = true
@@ -205,6 +216,7 @@ public:
   void        bvdCoding                ( Mv &rMvd );
   unsigned    xReadBvdContext(unsigned ctxT, int offset, int param);
 #endif
+#endif
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
   void        mvsdIdxFunc(PredictionUnit &pu, RefPicList eRefList);
   void        mvsdAffineIdxFunc(PredictionUnit &pu, RefPicList eRefList);
@@ -259,6 +271,9 @@ public:
   void        cu_lic_flag               ( CodingUnit& cu );
 #endif
 
+#if TEST_3_2
+  void        rribc_data                ( CodingUnit &cu );
+#endif
 #if JVET_Z0135_TEMP_CABAC_WIN_WEIGHT
   CABACDataStore*         m_CABACDataStore;
 #endif
diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp
index 4100e0e8..e5a2747d 100644
--- a/source/Lib/DecoderLib/DecCu.cpp
+++ b/source/Lib/DecoderLib/DecCu.cpp
@@ -1330,6 +1330,17 @@ void DecCu::xReconInter(CodingUnit &cu)
       cs.getRecoBuf(cu).get(COMPONENT_Y).rspSignal(m_pcReshape->getFwdLUT());
     }
   }
+#if TEST_3_2
+  if (CU::isIBC(cu) && cu.rribcFlipType)
+  {
+    cu.cs->getRecoBuf(cu).get(COMPONENT_Y).flipSignal(cu.rribcFlipType == 1);
+    if (isChromaEnabled(cu.chromaFormat) && cu.Cb().valid())
+    {
+      cu.cs->getRecoBuf(cu).get(COMPONENT_Cb).flipSignal(cu.rribcFlipType == 1);
+      cu.cs->getRecoBuf(cu).get(COMPONENT_Cr).flipSignal(cu.rribcFlipType == 1);
+    }
+  }
+#endif
 #endif
 
   DTRACE    ( g_trace_ctx, D_TMP, "reco " );
@@ -1457,6 +1468,12 @@ void DecCu::xDecodeInterTU( TransformUnit & currTU, const ComponentID compID )
     else
     {
       currTU.cs->getRecoBuf( currTU.blocks[currCompID] ).reconstruct( cs.getPredBuf( currTU.blocks[currCompID] ), compResiBuf, currTU.cu->cs->slice->clpRng( currCompID ) );
+#if TEST_3_2
+      if (CU::isIBC(*currTU.cu) && currTU.cu->rribcFlipType)
+      {
+        currTU.cs->getRecoBuf(currTU.blocks[currCompID]).flipSignal(currTU.cu->rribcFlipType == 1);
+      }
+#endif
     }
   }
 #endif
@@ -1477,7 +1494,21 @@ void DecCu::xDecodeInterTexture(CodingUnit &cu)
     {
       cs.getRecoBuf(cu).get(COMPONENT_Y).rspSignal(m_pcReshape->getFwdLUT());
     }
+
+#if TEST_3_2
+    if (CU::isIBC(cu) && cu.rribcFlipType)
+    {
+      cu.cs->getRecoBuf(cu).get(COMPONENT_Y).flipSignal(cu.rribcFlipType == 1);
+      if (isChromaEnabled(cu.chromaFormat) && cu.Cb().valid())
+      {
+        cu.cs->getRecoBuf(cu).get(COMPONENT_Cb).flipSignal(cu.rribcFlipType == 1);
+        cu.cs->getRecoBuf(cu).get(COMPONENT_Cr).flipSignal(cu.rribcFlipType == 1);
+      }
+    }
+#endif
 #endif
+
+
     return;
   }
 
@@ -2270,6 +2301,16 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
           }
           pu.mv[REF_PIC_LIST_0] = amvpInfo.mvCand[pu.mvpIdx[REF_PIC_LIST_0]] + mvd;
           pu.mv[REF_PIC_LIST_0].mvCliptoStorageBitDepth();
+#if TEST_3_2
+          if (pu.cu->rribcFlipType == 1)
+          {
+            pu.mv[REF_PIC_LIST_0].setVer(0);
+          }
+          else if (pu.cu->rribcFlipType == 2)
+          {
+            pu.mv[REF_PIC_LIST_0].setHor(0);
+          }
+#endif
 #if JVET_Z0160_IBC_ZERO_PADDING
           pu.bv = pu.mv[0];
           pu.bv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT);
diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp
index 7a402ecf..d8ac034c 100644
--- a/source/Lib/EncoderLib/CABACWriter.cpp
+++ b/source/Lib/EncoderLib/CABACWriter.cpp
@@ -2595,6 +2595,9 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu )
   {
     merge_flag( pu );
   }
+#if TEST_3_2
+  rribc_data(*pu.cu);
+#endif
   if( pu.mergeFlag )
   {
     merge_data(pu);
@@ -2615,10 +2618,18 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu )
     ref_idx(pu, REF_PIC_LIST_0);
     Mv mvd = pu.mvd[REF_PIC_LIST_0];
     mvd.changeIbcPrecInternal2Amvr(pu.cu->imv);
+#if TEST_3_2
+#if JVET_Z0131_IBC_BVD_BINARIZATION
+    bvdCoding(mvd, 0, pu.cu->rribcFlipType); // already changed to signaling precision
+#else
+    mvd_coding(mvd, 0, true, pu.cu->rribcFlipType); // already changed to signaling precision
+#endif
+#else
 #if JVET_Z0131_IBC_BVD_BINARIZATION
     bvdCoding(mvd, 0); // already changed to signaling precision
 #else
     mvd_coding(mvd, 0); // already changed to signaling precision
+#endif
 #endif
     if (pu.cs->sps->getMaxNumIBCMergeCand() == 1)
     {
@@ -4434,6 +4445,9 @@ void CABACWriter::mvd_coding( const Mv &rMvd, int8_t imv
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
   , bool codeSign
 #endif
+#if TEST_3_2
+  , const int &rribc_flip_type
+#endif
 )
 {
   int       horMvd = rMvd.getHor();
@@ -4461,8 +4475,19 @@ void CABACWriter::mvd_coding( const Mv &rMvd, int8_t imv
 
 
   // abs_mvd_greater0_flag[ 0 | 1 ]
-  m_BinEncoder.encodeBin( (horAbs > 0), Ctx::Mvd() );
-  m_BinEncoder.encodeBin( (verAbs > 0), Ctx::Mvd() );
+#if TEST_3_2
+  if (rribc_flip_type != 2)
+  {
+    m_BinEncoder.encodeBin((horAbs > 0), Ctx::Mvd());
+  }
+  if (rribc_flip_type != 1)
+  {
+    m_BinEncoder.encodeBin((verAbs > 0), Ctx::Mvd());
+  }
+#else
+  m_BinEncoder.encodeBin((horAbs > 0), Ctx::Mvd());
+  m_BinEncoder.encodeBin((verAbs > 0), Ctx::Mvd());
+#endif
 
   // abs_mvd_greater1_flag[ 0 | 1 ]
   if( horAbs > 0 )
@@ -4536,7 +4561,11 @@ void CABACWriter::xWriteBvdContext(unsigned uiSymbol, unsigned ctxT, int offset,
 #endif
 
 #if JVET_Z0131_IBC_BVD_BINARIZATION
-void CABACWriter::bvdCoding( const Mv &rMvd, int8_t imv )
+#if TEST_3_2
+void CABACWriter::bvdCoding(const Mv &rMvd, int8_t imv, const int &rribc_flip_type)
+#else
+void CABACWriter::bvdCoding( const Mv &rMvd, int8_t imv)
+#endif
 {
   int       horMvd = rMvd.getHor();
   int       verMvd = rMvd.getVer();
@@ -4544,8 +4573,19 @@ void CABACWriter::bvdCoding( const Mv &rMvd, int8_t imv )
   unsigned  horAbs  = unsigned( horMvd < 0 ? -horMvd : horMvd );
   unsigned  verAbs  = unsigned( verMvd < 0 ? -verMvd : verMvd );
 
+#if TEST_3_2
+  if (rribc_flip_type != 2)
+  {
+    m_BinEncoder.encodeBin((horAbs > 0), Ctx::Bvd(HOR_BVD_CTX_OFFSET));
+  }
+  if (rribc_flip_type != 1)
+  {
+    m_BinEncoder.encodeBin((verAbs > 0), Ctx::Bvd(VER_BVD_CTX_OFFSET));
+  }
+#else
   m_BinEncoder.encodeBin( (horAbs > 0), Ctx::Bvd(HOR_BVD_CTX_OFFSET) );
   m_BinEncoder.encodeBin( (verAbs > 0), Ctx::Bvd(VER_BVD_CTX_OFFSET) );
+#endif
 
   if( horAbs > 0 )
   {
@@ -6184,6 +6224,25 @@ void CABACWriter::cu_lic_flag(const CodingUnit& cu)
 }
 #endif
 
+#if TEST_3_2
+void CABACWriter::rribc_data(const CodingUnit& cu)
+{
+  if (!CU::isIBC(cu) || cu.firstPU->mergeFlag)
+  {
+    return;
+  }
+
+  unsigned ctxId = DeriveCtx::CtxRribcFlipType(cu);
+  m_BinEncoder.encodeBin(cu.rribcFlipType > 0, Ctx::rribcFlipType(ctxId));
+  if (cu.rribcFlipType)
+  {
+    CHECK(cu.rribcFlipType != 1 && cu.rribcFlipType != 2, "cu.rribcFlipType != 1 && cu.rribcFlipType != 2");
+    m_BinEncoder.encodeBin(cu.rribcFlipType >> 1, Ctx::rribcFlipType(3));
+  }
+  DTRACE(g_trace_ctx, D_SYNTAX, "rribc_data() rribcFlipType = %d\n", cu.rribcFlipType);
+}
+#endif
+
 #if SIGN_PREDICTION
 #if JVET_Y0141_SIGN_PRED_IMPROVE
 struct signCombInfo
diff --git a/source/Lib/EncoderLib/CABACWriter.h b/source/Lib/EncoderLib/CABACWriter.h
index 61eee126..34d9b29f 100644
--- a/source/Lib/EncoderLib/CABACWriter.h
+++ b/source/Lib/EncoderLib/CABACWriter.h
@@ -221,15 +221,28 @@ public:
   void        cbf_comp                  ( const CodingStructure&        cs,       bool              cbf,    const CompArea& area, unsigned depth, const bool prevCbf = false, const bool useISP = false );
 
   // mvd coding (clause 7.3.8.9)
+#if TEST_3_2
+#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
+  void        mvd_coding                ( const Mv &rMvd, int8_t imv, bool codeSign = true, const int &rribc_flip_type = 0 );
+#else
+  void        mvd_coding                ( const Mv &rMvd, int8_t imv, const int &rribc_flip_type = 0 );
+#endif
+#if JVET_Z0131_IBC_BVD_BINARIZATION
+  void        bvdCoding                ( const Mv &rMvd, int8_t imv, const int &rribc_flip_type = 0 );
+  void        xWriteBvdContext(unsigned uiSymbol, unsigned ctxT, int offset, int param);
+#endif
+#else
   void        mvd_coding                ( const Mv &rMvd, int8_t imv 
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
     , bool codeSign = true
 #endif
   );
+
 #if JVET_Z0131_IBC_BVD_BINARIZATION
   void        bvdCoding                ( const Mv &rMvd, int8_t imv );
   void        xWriteBvdContext(unsigned uiSymbol, unsigned ctxT, int offset, int param);
 #endif
+#endif
 #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
   void mvsdIdxFunc(const PredictionUnit &pu, RefPicList eRefList);
   void mvsdAffineIdxFunc(const PredictionUnit &pu, RefPicList eRefList);
@@ -278,6 +291,9 @@ public:
   void        cu_lic_flag               ( const CodingUnit& cu );
 #endif
 
+#if TEST_3_2
+  void        rribc_data                ( const CodingUnit &cu);
+#endif
 #if JVET_Z0135_TEMP_CABAC_WIN_WEIGHT
   CABACDataStore*         m_CABACDataStore;
 #endif
diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp
index 5e9c017d..8973eb16 100644
--- a/source/Lib/EncoderLib/EncCu.cpp
+++ b/source/Lib/EncoderLib/EncCu.cpp
@@ -1296,6 +1296,22 @@ void EncCu::xCompressCU( CodingStructure*& tempCS, CodingStructure*& bestCS, Par
     }
     else if (currTestMode.type == ETM_IBC)
     {
+#if TEST_3_2
+      if (m_pcEncCfg->getIntraPeriod() <= 1)
+      {
+        CodedCUInfo &relatedCU = ((EncModeCtrlMTnoRQT *) m_modeCtrl)->getBlkInfo(partitioner.currArea());
+        if (!relatedCU.isRribcTested)
+        {
+          xCheckRDCostIBCMode(tempCS, bestCS, partitioner, currTestMode);
+          relatedCU.isRribcTested = 1;
+        }
+        else
+        {
+          xCheckRDCostIBCMode(tempCS, bestCS, partitioner, currTestMode, true);
+        }
+      }
+      else
+#endif
       xCheckRDCostIBCMode(tempCS, bestCS, partitioner, currTestMode);
 #if JVET_Y0152_TT_ENC_SPEEDUP
       splitRdCostBest[CTU_LEVEL] = bestCS->cost;
@@ -9592,9 +9608,15 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
 #if INTER_LIC
     cu.LICFlag = false;
 #endif
-
     cu.geoFlag = false;
+#if TEST_3_2
+    cu.rribcFlipType = 0;
+    pu.mergeFlag = true;
+    PU::getIBCMergeCandidates(pu, mergeCtx);
+    pu.mergeFlag = false;
+#else
     PU::getIBCMergeCandidates(pu, mergeCtx);
+#endif
 #if JVET_Y0058_IBC_LIST_MODIFY && JVET_W0090_ARMC_TM
 #if JVET_Z0075_IBC_HMVP_ENLARGE
     m_pcInterSearch->adjustIBCMergeCandidates(pu, mergeCtx, 0, IBC_MRG_MAX_NUM_CANDS_MEM);
@@ -9605,7 +9627,13 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
 
 #if JVET_Z0084_IBC_TM && TM_MRG
     pu.tmMergeFlag = true;
+#if TEST_3_2
+    pu.mergeFlag = true;
     PU::getIBCMergeCandidates(pu, mergeCtxTm);
+    pu.mergeFlag = false;
+#else
+    PU::getIBCMergeCandidates(pu, mergeCtxTm);
+#endif
 #if JVET_Y0058_IBC_LIST_MODIFY && JVET_W0090_ARMC_TM
 #if JVET_Z0075_IBC_HMVP_ENLARGE
     m_pcInterSearch->adjustIBCMergeCandidates(pu, mergeCtxTm, 0, IBC_MRG_MAX_NUM_CANDS_MEM);
@@ -9679,6 +9707,28 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
       Picture* refPic = pu.cu->slice->getPic();
       const CPelBuf refBuf = refPic->getRecoBuf(pu.blocks[COMPONENT_Y]);
       const Pel*        piRefSrch = refBuf.buf;
+#if TEST_3_2
+      pu.cu->rribcFlipType = 0;
+      const CompArea &area = cu.blocks[COMPONENT_Y];
+      CompArea        tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
+      PelBuf          tmpOrgLuma = m_tmpStorageLCU->getBuf(tmpArea);
+      tmpOrgLuma.copyFrom(tempCS->getOrgBuf().Y());
+      if (tempCS->slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag())
+      {
+        tmpOrgLuma.rspSignal(tempCS->getOrgBuf().Y(), m_pcReshape->getFwdLUT());
+      }
+      PelStorage m_tmpStorageCUflipH;
+      m_tmpStorageCUflipH.create(UnitArea(pu.chromaFormat, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE)));
+      PelBuf tmpOrgLumaFlipH = m_tmpStorageCUflipH.getBuf(tmpArea);
+      tmpOrgLumaFlipH.copyFrom(tmpOrgLuma);
+      tmpOrgLumaFlipH.flipSignal(true);
+
+      PelStorage m_tmpStorageCUflipV;
+      m_tmpStorageCUflipV.create(UnitArea(pu.chromaFormat, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE)));
+      PelBuf tmpOrgLumaFlipV = m_tmpStorageCUflipV.getBuf(tmpArea);
+      tmpOrgLumaFlipV.copyFrom(tmpOrgLuma);
+      tmpOrgLumaFlipV.flipSignal(false);
+#else
       if (tempCS->slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag())
       {
         const CompArea &area = cu.blocks[COMPONENT_Y];
@@ -9689,6 +9739,7 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
       }
       else
         m_pcRdCost->setDistParam(distParam, tempCS->getOrgBuf().Y(), refBuf, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, bUseHadamard);
+#endif
 
       int refStride = refBuf.stride;
 #if !JVET_Y0058_IBC_LIST_MODIFY
@@ -9728,6 +9779,21 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
         }
         PU::spanMotionInfo(pu, mergeCtx);
 
+#if TEST_3_2
+        if (pu.cu->rribcFlipType == 0)
+        {
+          m_pcRdCost->setDistParam(distParam, tmpOrgLuma, refBuf, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, bUseHadamard);
+        }
+        else if (pu.cu->rribcFlipType == 1)
+        {
+          m_pcRdCost->setDistParam(distParam, tmpOrgLumaFlipH, refBuf, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, bUseHadamard);
+        }
+        else
+        {
+          m_pcRdCost->setDistParam(distParam, tmpOrgLumaFlipV, refBuf, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, bUseHadamard);
+        }
+#endif
+
         distParam.cur.buf = piRefSrch + refStride * yPred + xPred;
 
         Distortion sad = distParam.distFunc(distParam);
@@ -9782,6 +9848,20 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
       }
       PU::spanMotionInfo(pu, mergeCtxTm);
 
+#if TEST_3_2
+      if (pu.cu->rribcFlipType == 0)
+      {
+        m_pcRdCost->setDistParam(distParam, tmpOrgLuma, refBuf, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, bUseHadamard);
+      }
+      else if (pu.cu->rribcFlipType == 1)
+      {
+        m_pcRdCost->setDistParam(distParam, tmpOrgLumaFlipH, refBuf, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, bUseHadamard);
+      }
+      else
+      {
+        m_pcRdCost->setDistParam(distParam, tmpOrgLumaFlipV, refBuf, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, bUseHadamard);
+      }
+#endif
       distParam.cur.buf = piRefSrch + refStride * yPred + xPred;
 
       Distortion sad = distParam.distFunc(distParam);
@@ -9795,6 +9875,10 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
       updateCandList(mergeCand+mergeCtx.numValidMergeCand, cost, RdModeList, candCostList, numMrgSATDCand);
     }
 #endif
+#if TEST_3_2
+    m_tmpStorageCUflipH.destroy();
+    m_tmpStorageCUflipV.destroy();
+#endif
 
       // Try to limit number of candidates using SATD-costs
       if (numValidBv)
@@ -9853,6 +9937,9 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
             cu.LICFlag = false;
 #endif
 
+#if TEST_3_2
+            cu.rribcFlipType = 0;
+#endif
             PredictionUnit &pu = tempCS->addPU(cu, partitioner.chType);// tempCS->addPU(cu);
             pu.intraDir[0] = DC_IDX; // set intra pred for ibc block
             pu.intraDir[1] = PLANAR_IDX; // set intra pred for ibc block
@@ -9927,7 +10014,11 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
   }
 }
 
+#if TEST_3_2
+void EncCu::xCheckRDCostIBCMode( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode, bool isSecondPass)
+#else
 void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode)
+#endif
 {
 #if CTU_256
   if( tempCS->area.lwidth() >= 128 || tempCS->area.lheight() >= 128 ) // disable IBC mode larger than 64x64
@@ -9971,7 +10062,12 @@ void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&best
 
     pu.interDir = 1; // use list 0 for IBC mode
     pu.refIdx[REF_PIC_LIST_0] = MAX_NUM_REF; // last idx in the list
+#if TEST_3_2
+      pu.cu->rribcFlipType = 0;
+      bool bValid = m_pcInterSearch->predIBCSearch(cu, partitioner, m_ctuIbcSearchRangeX, m_ctuIbcSearchRangeY, m_ibcHashMap, isSecondPass);
+#else
       bool bValid = m_pcInterSearch->predIBCSearch(cu, partitioner, m_ctuIbcSearchRangeX, m_ctuIbcSearchRangeY, m_ibcHashMap);
+#endif
 
       if (bValid)
       {
diff --git a/source/Lib/EncoderLib/EncCu.h b/source/Lib/EncoderLib/EncCu.h
index 793a9bf3..a3c076b0 100644
--- a/source/Lib/EncoderLib/EncCu.h
+++ b/source/Lib/EncoderLib/EncCu.h
@@ -540,8 +540,13 @@ protected:
        && (abs(cu.slice->getPOC() - cu.slice->getRefPOC(REF_PIC_LIST_0, cu.refIdxBi[0])) == 1
        ||  abs(cu.slice->getPOC() - cu.slice->getRefPOC(REF_PIC_LIST_1, cu.refIdxBi[1])) == 1))));
   }
+#if TEST_3_2
+  void xCheckRDCostIBCMode    ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode, bool isSecondPass = false );
+#else
   void xCheckRDCostIBCMode    ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode );
-  void xCheckRDCostIBCModeMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode );
+#endif
+  void xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner,      \
+                                    const EncTestMode &encTestMode);
 
   void xCheckPLT              ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode );
 };
diff --git a/source/Lib/EncoderLib/EncModeCtrl.cpp b/source/Lib/EncoderLib/EncModeCtrl.cpp
index 3b87cc63..2ed6f8a6 100644
--- a/source/Lib/EncoderLib/EncModeCtrl.cpp
+++ b/source/Lib/EncoderLib/EncModeCtrl.cpp
@@ -2259,6 +2259,9 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt
         }
         else if (CU::isIBC(*bestCU))
         {
+#if TEST_3_2
+          relatedCU.isRribcCoded = bestCU->rribcFlipType > 0;
+#endif
           relatedCU.isIBC = true;
           relatedCU.isSkip |= bestCU->skip;
           if (bestCU->slice->getSPS()->getUseColorTrans())
diff --git a/source/Lib/EncoderLib/EncModeCtrl.h b/source/Lib/EncoderLib/EncModeCtrl.h
index e347c668..1f94c015 100644
--- a/source/Lib/EncoderLib/EncModeCtrl.h
+++ b/source/Lib/EncoderLib/EncModeCtrl.h
@@ -966,6 +966,10 @@ struct CodedCUInfo
   int     numGeoDirCand;
   int     geoMrgIdx0List[GEO_MAX_TRY_WEIGHTED_SATD];
   int     geoMrgIdx1List[GEO_MAX_TRY_WEIGHTED_SATD];
+#endif
+#if TEST_3_2
+  bool    isRribcCoded;
+  bool    isRribcTested;
 #endif
   bool validMv[NUM_REF_PIC_LIST_01][MAX_STORED_CU_INFO_REFS];
   Mv   saveMv [NUM_REF_PIC_LIST_01][MAX_STORED_CU_INFO_REFS];
diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp
index 45b45f82..289fb1d7 100644
--- a/source/Lib/EncoderLib/EncSlice.cpp
+++ b/source/Lib/EncoderLib/EncSlice.cpp
@@ -1754,7 +1754,11 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons
 
   if( ( !pcSlice->isIntra() && pcSlice->getSPS()->getFpelMmvdEnabledFlag() ) || ( pcSlice->getSPS()->getIBCFlag() && m_pcCuEncoder->getEncCfg()->getIBCHashSearch() ) )
   {
+#if TEST_3_2
+    m_pcCuEncoder->getIbcHashMap().rebuildPicHashMap(cs.picture->getTrueOrigBuf(), CS::isDualITree(cs));
+#else
     m_pcCuEncoder->getIbcHashMap().rebuildPicHashMap(cs.picture->getTrueOrigBuf());
+#endif
     if (m_pcCfg->getIntraPeriod() != -1)
     {
       int hashBlkHitPerc = m_pcCuEncoder->getIbcHashMap().calHashBlkMatchPerc(cs.area.Y());
diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp
index ad6b6ca2..c366af4a 100644
--- a/source/Lib/EncoderLib/InterSearch.cpp
+++ b/source/Lib/EncoderLib/InterSearch.cpp
@@ -915,6 +915,9 @@ void InterSearch::xIBCSearchMVCandUpdate(Distortion  sad, int x, int y, Distorti
   }
 }
 
+#if TEST_3_2
+int InterSearch::xIBCSearchMVChromaRefine( PredictionUnit& pu, int roiWidth, int roiHeight, int cuPelX, int cuPelY, Distortion* sadBestCand, Mv* cMVCand, int rribcFlipType )
+#else
 int InterSearch::xIBCSearchMVChromaRefine(PredictionUnit& pu,
   int         roiWidth,
   int         roiHeight,
@@ -922,8 +925,8 @@ int InterSearch::xIBCSearchMVChromaRefine(PredictionUnit& pu,
   int         cuPelY,
   Distortion* sadBestCand,
   Mv*     cMVCand
-
 )
+#endif
 {
   if ( (!isChromaEnabled(pu.chromaFormat)) || (!pu.Cb().valid()) )
   {
@@ -949,6 +952,12 @@ int InterSearch::xIBCSearchMVChromaRefine(PredictionUnit& pu,
     {
       continue;
     }
+#if TEST_3_2
+    if ((rribcFlipType == 1 && cMVCand[cand].getVer() != 0) || (rribcFlipType == 2 && cMVCand[cand].getHor() != 0))
+    {
+      continue;
+    }
+#endif
 
     if ((!cMVCand[cand].getHor()) && (!cMVCand[cand].getVer()))
       continue;
@@ -976,7 +985,22 @@ int InterSearch::xIBCSearchMVChromaRefine(PredictionUnit& pu,
 
       PelUnitBuf origBuf = pu.cs->getOrgBuf(allCompBlocks);
       PelUnitBuf* pBuf = &origBuf;
+#if TEST_3_2
+      PelBuf tmpPattern;
+      if (rribcFlipType)
+      {
+        CompArea tmpArea(ComponentID(ch), pu.chromaFormat, Position(0, 0), Size(pBuf->get(ComponentID(ch)).width, pBuf->get(ComponentID(ch)).height));
+        tmpPattern = m_tmpStorageLCU.getBuf(tmpArea);
+        tmpPattern.copyFrom(pBuf->get(ComponentID(ch)));
+        tmpPattern.flipSignal(rribcFlipType == 1);
+      }
+      else
+      {
+        tmpPattern = pBuf->get(ComponentID(ch));
+      }
+#else
       CPelBuf  tmpPattern = pBuf->get(ComponentID(ch));
+#endif
       pOrg = (Pel*)tmpPattern.buf;
 
       Picture* refPic = pu.cu->slice->getPic();
@@ -1042,7 +1066,11 @@ static unsigned int xMergeCandLists(Mv *dst, unsigned int dn, unsigned int dstTo
   return dn;
 }
 
-void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cStruct, Mv& rcMv, Distortion&  ruiCost, Mv*  pcMvSrchRngLT, Mv*  pcMvSrchRngRB, Mv* pcMvPred)
+#if TEST_3_2
+void InterSearch::xIntraPatternSearch( PredictionUnit &pu, IntTZSearchStruct &cStruct, Mv &rcMv, Distortion &ruiCost, Mv *pcMvSrchRngLT, Mv *pcMvSrchRngRB, Mv *pcMvPred, int rribcFlipType )
+#else
+void InterSearch::xIntraPatternSearch(PredictionUnit &pu, IntTZSearchStruct &cStruct, Mv &rcMv, Distortion &ruiCost, Mv *pcMvSrchRngLT, Mv *pcMvSrchRngRB, Mv *pcMvPred)
+#endif
 {
   const int   srchRngHorLeft = pcMvSrchRngLT->getHor();
   const int   srchRngHorRight = pcMvSrchRngRB->getHor();
@@ -1103,6 +1131,13 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
       int xPred = m_acBVs[cand].getHor();
       int yPred = m_acBVs[cand].getVer();
 
+#if TEST_3_2
+      if ((rribcFlipType == 1 && yPred != 0) || (rribcFlipType == 2 && xPred != 0))
+      {
+        continue;
+      }
+#endif
+
       if (!(xPred == 0 && yPred == 0)
         && !((yPred < srTop) || (yPred > srBottom))
         && !((xPred < srLeft) || (xPred > srRight)))
@@ -1115,7 +1150,11 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
 
         if (validCand)
         {
+#if TEST_3_2
+          sad = m_pcRdCost->getBvCostMultiplePreds(xPred, yPred, pu.cs->sps->getAMVREnabledFlag(), rribcFlipType);
+#else
           sad = m_pcRdCost->getBvCostMultiplePreds(xPred, yPred, pu.cs->sps->getAMVREnabledFlag());
+#endif
           m_cDistParam.cur.buf = piRefSrch + cStruct.iRefStride * yPred + xPred;
           sad += m_cDistParam.distFunc(m_cDistParam);
 
@@ -1132,6 +1171,12 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
     const int boundY = (0 - roiHeight - puPelOffsetY);
     for (int y = std::max(srchRngVerTop, 0 - cuPelY); y <= boundY; ++y)
     {
+#if TEST_3_2
+      if (rribcFlipType == 1 && y != 0)
+      {
+        continue;
+      }
+#endif
 #if JVET_Z0084_IBC_TM
       if (!PU::searchBv(pu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, 0, y, lcuWidth))
 #else
@@ -1141,7 +1186,11 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
         continue;
       }
 
+#if TEST_3_2
+      sad = m_pcRdCost->getBvCostMultiplePreds(0, y, pu.cs->sps->getAMVREnabledFlag(), rribcFlipType);
+#else
       sad = m_pcRdCost->getBvCostMultiplePreds(0, y, pu.cs->sps->getAMVREnabledFlag());
+#endif
       m_cDistParam.cur.buf = piRefSrch + cStruct.iRefStride * y;
       sad += m_cDistParam.distFunc(m_cDistParam);
 
@@ -1161,6 +1210,12 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
     const int boundX = std::max(srchRngHorLeft, -cuPelX);
     for (int x = 0 - roiWidth - puPelOffsetX; x >= boundX; --x)
     {
+#if TEST_3_2
+      if (rribcFlipType == 2 && x != 0)
+      {
+        continue;
+      }
+#endif
 #if JVET_Z0084_IBC_TM
       if (!PU::searchBv(pu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, x, 0, lcuWidth))
 #else
@@ -1170,7 +1225,11 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
         continue;
       }
 
+#if TEST_3_2
+      sad = m_pcRdCost->getBvCostMultiplePreds(x, 0, pu.cs->sps->getAMVREnabledFlag(), rribcFlipType);
+#else
       sad = m_pcRdCost->getBvCostMultiplePreds(x, 0, pu.cs->sps->getAMVREnabledFlag());
+#endif
       m_cDistParam.cur.buf = piRefSrch + x;
       sad += m_cDistParam.distFunc(m_cDistParam);
 
@@ -1191,10 +1250,17 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
     bestX = cMVCand[0].getHor();
     bestY = cMVCand[0].getVer();
     sadBest = sadBestCand[0];
+#if TEST_3_2
+    if ((!bestX && !bestY) || (sadBest - m_pcRdCost->getBvCostMultiplePreds(bestX, bestY, pu.cs->sps->getAMVREnabledFlag(), rribcFlipType) <= 32))
+    {
+      //chroma refine
+      bestCandIdx = xIBCSearchMVChromaRefine(pu, roiWidth, roiHeight, cuPelX, cuPelY, sadBestCand, cMVCand, rribcFlipType);
+#else
     if ((!bestX && !bestY) || (sadBest - m_pcRdCost->getBvCostMultiplePreds(bestX, bestY, pu.cs->sps->getAMVREnabledFlag()) <= 32))
     {
       //chroma refine
       bestCandIdx = xIBCSearchMVChromaRefine(pu, roiWidth, roiHeight, cuPelX, cuPelY, sadBestCand, cMVCand);
+#endif
       bestX = cMVCand[bestCandIdx].getHor();
       bestY = cMVCand[bestCandIdx].getVer();
       sadBest = sadBestCand[bestCandIdx];
@@ -1214,20 +1280,44 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
 
       for (int y = std::max(verTop, -cuPelY); y <= verBottom; y += 2)
       {
+#if TEST_3_2
+        if (rribcFlipType == 1 && y != 0)
+        {
+          continue;
+        }
+#endif
         if ((y == 0) || ((int)(cuPelY + y + roiHeight) >= picHeight))
         {
           continue;
         }        
         for (int x = std::max(horLeft, -cuPelX); x <= horRight; x++)
         {
+#if TEST_3_2
+          if (rribcFlipType == 2 && x != 0)
+          {
+            continue;
+          }
+#endif
 #else
       for (int y = std::max(srchRngVerTop, -cuPelY); y <= srchRngVerBottom; y += 2)
       {
+#if TEST_3_2
+        if (rribcFlipType == 1 && y != 0)
+        {
+          continue;
+        }
+#endif
         if ((y == 0) || ((int)(cuPelY + y + roiHeight) >= picHeight))
           continue;
 
         for (int x = std::max(srchRngHorLeft, -cuPelX); x <= srchRngHorRight; x++)
         {
+#if TEST_3_2
+          if (rribcFlipType == 2 && x != 0)
+          {
+            continue;
+          }
+#endif
 #endif
           if ((x == 0) || ((int)(cuPelX + x + roiWidth) >= picWidth))
             continue;
@@ -1241,7 +1331,11 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
             continue;
           }
 
+#if TEST_3_2
+          sad = m_pcRdCost->getBvCostMultiplePreds(x, y, pu.cs->sps->getAMVREnabledFlag(), rribcFlipType);
+#else
           sad = m_pcRdCost->getBvCostMultiplePreds(x, y, pu.cs->sps->getAMVREnabledFlag());
+#endif
           m_cDistParam.cur.buf = piRefSrch + cStruct.iRefStride * y + x;
           sad += m_cDistParam.distFunc(m_cDistParam);
 
@@ -1252,11 +1346,16 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
       bestX = cMVCand[0].getHor();
       bestY = cMVCand[0].getVer();
       sadBest = sadBestCand[0];
+#if TEST_3_2
+      if (sadBest - m_pcRdCost->getBvCostMultiplePreds(bestX, bestY, pu.cs->sps->getAMVREnabledFlag(), rribcFlipType) <= 16)
+      {
+        bestCandIdx = xIBCSearchMVChromaRefine(pu, roiWidth, roiHeight, cuPelX, cuPelY, sadBestCand, cMVCand, rribcFlipType);
+#else
       if (sadBest - m_pcRdCost->getBvCostMultiplePreds(bestX, bestY, pu.cs->sps->getAMVREnabledFlag()) <= 16)
       {
-        //chroma refine
+        // chroma refine
         bestCandIdx = xIBCSearchMVChromaRefine(pu, roiWidth, roiHeight, cuPelX, cuPelY, sadBestCand, cMVCand);
-
+#endif
         bestX = cMVCand[bestCandIdx].getHor();
         bestY = cMVCand[bestCandIdx].getVer();
         sadBest = sadBestCand[bestCandIdx];
@@ -1268,6 +1367,12 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
 #if JVET_Z0153_IBC_EXT_REF
       for (int y = (std::max(verTop, -cuPelY) + 1); y <= verBottom; y += 2)
       {
+#if TEST_3_2
+        if (rribcFlipType == 1 && y != 0)
+        {
+          continue;
+        }
+#endif
         if ((y == 0) || ((int)(cuPelY + y + roiHeight) >= picHeight))
         {
           continue;
@@ -1277,12 +1382,24 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
 #else
       for (int y = (std::max(srchRngVerTop, -cuPelY) + 1); y <= srchRngVerBottom; y += 2)
       {
+#if TEST_3_2
+        if (rribcFlipType == 1 && y != 0)
+        {
+          continue;
+        }
+#endif
         if ((y == 0) || ((int)(cuPelY + y + roiHeight) >= picHeight))
           continue;
 
         for (int x = std::max(srchRngHorLeft, -cuPelX); x <= srchRngHorRight; x += 2)
 #endif
         {
+#if TEST_3_2
+          if (rribcFlipType == 2 && x != 0)
+          {
+            continue;
+          }
+#endif
           if ((x == 0) || ((int)(cuPelX + x + roiWidth) >= picWidth))
             continue;
 
@@ -1295,7 +1412,12 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
             continue;
           }
 
+#if TEST_3_2
+          sad = m_pcRdCost->getBvCostMultiplePreds(x, y, pu.cs->sps->getAMVREnabledFlag(), rribcFlipType);
+#else
           sad = m_pcRdCost->getBvCostMultiplePreds(x, y, pu.cs->sps->getAMVREnabledFlag());
+#endif
+
           m_cDistParam.cur.buf = piRefSrch + cStruct.iRefStride * y + x;
           sad += m_cDistParam.distFunc(m_cDistParam);
 
@@ -1303,8 +1425,12 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
           xIBCSearchMVCandUpdate(sad, x, y, sadBestCand, cMVCand);
           if (sadBestCand[0] <= 5)
           {
-            //chroma refine & return
+            // chroma refine & return
+#if TEST_3_2
+            bestCandIdx = xIBCSearchMVChromaRefine(pu, roiWidth, roiHeight, cuPelX, cuPelY, sadBestCand, cMVCand, rribcFlipType);
+#else
             bestCandIdx = xIBCSearchMVChromaRefine(pu, roiWidth, roiHeight, cuPelX, cuPelY, sadBestCand, cMVCand);
+#endif
             bestX = cMVCand[bestCandIdx].getHor();
             bestY = cMVCand[bestCandIdx].getVer();
             sadBest = sadBestCand[bestCandIdx];
@@ -1319,10 +1445,17 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
       bestY = cMVCand[0].getVer();
       sadBest = sadBestCand[0];
 
+#if TEST_3_2
+      if ((sadBest >= tempSadBest) || ((sadBest - m_pcRdCost->getBvCostMultiplePreds(bestX, bestY, pu.cs->sps->getAMVREnabledFlag(), rribcFlipType)) <= 32))
+      {
+        // chroma refine
+        bestCandIdx = xIBCSearchMVChromaRefine(pu, roiWidth, roiHeight, cuPelX, cuPelY, sadBestCand, cMVCand, rribcFlipType);
+#else
       if ((sadBest >= tempSadBest) || ((sadBest - m_pcRdCost->getBvCostMultiplePreds(bestX, bestY, pu.cs->sps->getAMVREnabledFlag())) <= 32))
       {
-        //chroma refine
+        // chroma refine
         bestCandIdx = xIBCSearchMVChromaRefine(pu, roiWidth, roiHeight, cuPelX, cuPelY, sadBestCand, cMVCand);
+#endif
         bestX = cMVCand[bestCandIdx].getHor();
         bestY = cMVCand[bestCandIdx].getVer();
         sadBest = sadBestCand[bestCandIdx];
@@ -1336,6 +1469,12 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
 #if JVET_Z0153_IBC_EXT_REF
       for (int y = (std::max(verTop, -cuPelY) + 1); y <= verBottom; y += 2)
       {
+#if TEST_3_2
+        if (rribcFlipType == 1 && y != 0)
+        {
+          continue;
+        }
+#endif
         if ((y == 0) || ((int)(cuPelY + y + roiHeight) >= picHeight))
         {
           continue;
@@ -1344,6 +1483,12 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
 #else
       for (int y = (std::max(srchRngVerTop, -cuPelY) + 1); y <= srchRngVerBottom; y += 2)
       {
+#if TEST_3_2
+        if (rribcFlipType == 1 && y != 0)
+        {
+          continue;
+        }
+#endif
         if ((y == 0) || ((int)(cuPelY + y + roiHeight) >= picHeight))
           continue;
 
@@ -1351,6 +1496,12 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
 #endif
         {
 
+#if TEST_3_2
+          if (rribcFlipType == 2 && x != 0)
+          {
+            continue;
+          }
+#endif
           if ((x == 0) || ((int)(cuPelX + x + roiWidth) >= picWidth))
             continue;
 
@@ -1363,7 +1514,11 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
             continue;
           }
 
+#if TEST_3_2
+          sad = m_pcRdCost->getBvCostMultiplePreds(x, y, pu.cs->sps->getAMVREnabledFlag(), rribcFlipType);
+#else
           sad = m_pcRdCost->getBvCostMultiplePreds(x, y, pu.cs->sps->getAMVREnabledFlag());
+#endif
           m_cDistParam.cur.buf = piRefSrch + cStruct.iRefStride * y + x;
           sad += m_cDistParam.distFunc(m_cDistParam);
 
@@ -1371,8 +1526,12 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
           xIBCSearchMVCandUpdate(sad, x, y, sadBestCand, cMVCand);
           if (sadBestCand[0] <= 5)
           {
-            //chroma refine & return
+            // chroma refine & return
+#if TEST_3_2
+            bestCandIdx = xIBCSearchMVChromaRefine(pu, roiWidth, roiHeight, cuPelX, cuPelY, sadBestCand, cMVCand, rribcFlipType);
+#else
             bestCandIdx = xIBCSearchMVChromaRefine(pu, roiWidth, roiHeight, cuPelX, cuPelY, sadBestCand, cMVCand);
+#endif
             bestX = cMVCand[bestCandIdx].getHor();
             bestY = cMVCand[bestCandIdx].getVer();
             sadBest = sadBestCand[bestCandIdx];
@@ -1385,7 +1544,11 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
     }
   }
 
+#if TEST_3_2
+  bestCandIdx = xIBCSearchMVChromaRefine(pu, roiWidth, roiHeight, cuPelX, cuPelY, sadBestCand, cMVCand, rribcFlipType);
+#else
   bestCandIdx = xIBCSearchMVChromaRefine(pu, roiWidth, roiHeight, cuPelX, cuPelY, sadBestCand, cMVCand);
+#endif
 
   bestX = cMVCand[bestCandIdx].getHor();
   bestY = cMVCand[bestCandIdx].getVer();
@@ -1403,10 +1566,28 @@ end:
 
   for (unsigned int cand = 0; cand < CHROMA_REFINEMENT_CANDIDATES; cand++)
   {
+#if TEST_3_2
+    if ((rribcFlipType == 1 && cMVCand[cand].getVer() != 0) || (rribcFlipType == 2 && cMVCand[cand].getHor() != 0))
+    {
+      continue;
+    }
+    if (m_pcEncCfg->getIntraPeriod() < 1 && m_pcEncCfg->getIBCFastMethod())
+    {
+      if (sadBestCand[cand] >= minCostProj)
+      {
+        break;
+      }
+      else if (!cand && rribcFlipType)
+      {
+        minCostProj =  3 * sadBestCand[0];
+      }
+    }
+#endif
     if (cMVCand[cand].getHor() == 0 && cMVCand[cand].getVer() == 0)
     {
       continue;
     }
+
     m_ctuRecord[pu.lumaPos()][pu.lumaSize()].bvRecord[cMVCand[cand]] = sadBestCand[cand];
   }
 
@@ -1416,11 +1597,11 @@ end:
 
 
 // based on xMotionEstimation
-void InterSearch::xIBCEstimation(PredictionUnit& pu, PelUnitBuf& origBuf,
-  Mv     *pcMvPred,
-  Mv     &rcMv,
-  Distortion &ruiCost, const int localSearchRangeX, const int localSearchRangeY
-)
+#if TEST_3_2
+void InterSearch::xIBCEstimation(PredictionUnit &pu, PelUnitBuf &origBuf, Mv pcMvPred[3][2], Mv &rcMv, Distortion &ruiCost, const int localSearchRangeX, const int localSearchRangeY, int numRribcType)
+#else
+void InterSearch::xIBCEstimation(PredictionUnit& pu, PelUnitBuf& origBuf, Mv *pcMvPred, Mv &rcMv, Distortion &ruiCost, const int localSearchRangeX, const int localSearchRangeY)
+#endif
 {
   const int iPicWidth = pu.cs->slice->getPPS()->getPicWidthInLumaSamples();
   const int iPicHeight = pu.cs->slice->getPPS()->getPicHeightInLumaSamples();
@@ -1436,7 +1617,47 @@ void InterSearch::xIBCEstimation(PredictionUnit& pu, PelUnitBuf& origBuf,
   CPelBuf  tmpPattern = pBuf->Y();
   CPelBuf* pcPatternKey = &tmpPattern;
   PelBuf tmpOrgLuma;
+#if TEST_3_2
+  const CompArea &area = pu.blocks[COMPONENT_Y];
+  CompArea        tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
+  if ((pu.cs->slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()))
+  {
+    tmpOrgLuma = m_tmpStorageLCU.getBuf(tmpArea);
+    tmpOrgLuma.rspSignal(tmpPattern, m_pcReshape->getFwdLUT());
+    pcPatternKey = (CPelBuf *) &tmpOrgLuma;
+  }
+
+  CPelBuf   *pcPatternKeyFlipH;
+  CPelBuf   *pcPatternKeyFlipV;
+  PelStorage m_tmpStorageCUflipH;
+  PelStorage m_tmpStorageCUflipV;
+  PelBuf tmpOrgLumaFlipH, tmpOrgLumaFlipV;
+
+  if (numRribcType > 1)
+  {
+    m_tmpStorageCUflipH.create(UnitArea(pu.chromaFormat, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE)));
+    tmpOrgLumaFlipH = m_tmpStorageCUflipH.getBuf(tmpArea);
+
+    m_tmpStorageCUflipV.create(UnitArea(pu.chromaFormat, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE)));
+    tmpOrgLumaFlipV = m_tmpStorageCUflipV.getBuf(tmpArea);
+
+    if ((pu.cs->slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()))
+    {
+      tmpOrgLumaFlipH.copyFrom(tmpOrgLuma);
+      tmpOrgLumaFlipV.copyFrom(tmpOrgLuma);
+    }
+    else
+    {
+      tmpOrgLumaFlipH.copyFrom(tmpPattern);
+      tmpOrgLumaFlipV.copyFrom(tmpPattern);
+    }
+    tmpOrgLumaFlipH.flipSignal(true);
+    pcPatternKeyFlipH = (CPelBuf *) &tmpOrgLumaFlipH;
 
+    tmpOrgLumaFlipV.flipSignal(false);
+    pcPatternKeyFlipV = (CPelBuf *) &tmpOrgLumaFlipV;
+  }
+#else
   if ((pu.cs->slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()))
   {
     const CompArea &area = pu.blocks[COMPONENT_Y];
@@ -1445,13 +1666,16 @@ void InterSearch::xIBCEstimation(PredictionUnit& pu, PelUnitBuf& origBuf,
     tmpOrgLuma.rspSignal( tmpPattern, m_pcReshape->getFwdLUT() );
     pcPatternKey = (CPelBuf*)&tmpOrgLuma;
   }
+#endif
 
   m_lumaClpRng = pu.cs->slice->clpRng(COMPONENT_Y);
   Picture* refPic = pu.cu->slice->getPic();
   const CPelBuf refBuf = refPic->getRecoBuf(pu.blocks[COMPONENT_Y]);
 
   IntTZSearchStruct cStruct;
+#if !TEST_3_2
   cStruct.pcPatternKey = pcPatternKey;
+#endif
   cStruct.iRefStride = refBuf.stride;
   cStruct.piRefY = refBuf.buf;
   CHECK(pu.cu->imv == IMV_HPEL, "IF_IBC");
@@ -1466,15 +1690,188 @@ void InterSearch::xIBCEstimation(PredictionUnit& pu, PelUnitBuf& origBuf,
   m_pcRdCost->setCostScale(0);
 
   m_cDistParam.useMR = false;
+#if !TEST_3_2
   m_pcRdCost->setDistParam(m_cDistParam, *cStruct.pcPatternKey, cStruct.piRefY, cStruct.iRefStride, m_lumaClpRng.bd, COMPONENT_Y, cStruct.subShiftMode);
+#endif
   bool buffered = false;
+#if TEST_3_2
+  minCostProj = MAX_INT;
+  if (m_pcEncCfg->getIntraPeriod() < 1 && m_pcEncCfg->getIBCFastMethod())
+  {
+    ruiCost  = MAX_UINT;
+    std::unordered_map<Mv, Distortion> &history = m_ctuRecord[pu.lumaPos()][pu.lumaSize()].bvRecord;
+    if (history.size())
+    {
+      std::vector<std::pair<Mv, Distortion>> historyOrdered(history.size());
+      int                                    i = 0;
+      for (std::unordered_map<Mv, Distortion>::iterator p = history.begin(); p != history.end(); p++)
+      {
+        historyOrdered[i] = { p->first, p->second };
+        i++;
+      }
+      std::stable_sort(historyOrdered.begin(), historyOrdered.end(),
+                       [](const std::pair<Mv, Distortion> &l, const std::pair<Mv, Distortion> &r)
+                       { return (l.second < r.second) || (l.second == r.second && (l.first.getHor() < r.first.getHor() || l.first.getVer() < r.first.getVer()) ); });
+      minCostProj = 3 * historyOrdered[0].second;
+
+      Distortion cand0Cost[3] = { MAX_UINT, MAX_UINT, MAX_UINT };
+      bool       isCalc[3] = { false }, isSkip[3] = { false }, checkDone[3] = { false };
+      int        map[6] = { 1, 2, 0, 2, 0, 1 };
+      for (int i = 0; i < history.size(); i++)
+      {
+        if (historyOrdered[i].second >= minCostProj)
+        {
+          break;
+        }
+        const Mv &bv  = historyOrdered[i].first;
+        int       xBv = bv.hor;
+        int       yBv = bv.ver;
+
+        for (int rribcFlipType = 0; rribcFlipType < numRribcType; rribcFlipType++)
+        {
+          if (isSkip[rribcFlipType])
+          {
+            continue;
+          }
+          if (!checkDone[rribcFlipType] && isCalc[rribcFlipType] && (isCalc[map[rribcFlipType * 2]] || isCalc[map[rribcFlipType * 2 + 1]]))
+          {
+            if (isCalc[map[rribcFlipType * 2]] && cand0Cost[rribcFlipType] >= 1.1 * cand0Cost[map[rribcFlipType * 2]])
+            {
+              isSkip[rribcFlipType] = true;
+            }
+            else if (isCalc[map[rribcFlipType * 2]] && cand0Cost[rribcFlipType] >= 1.1 * cand0Cost[map[rribcFlipType * 2 + 1]])
+            {
+              isSkip[rribcFlipType] = true;
+            }
+            checkDone[rribcFlipType] = true;
+          }
+          if ((rribcFlipType == 1 && yBv != 0) || (rribcFlipType == 2 && xBv != 0))
+          {
+            continue;
+          }
+#if JVET_Z0084_IBC_TM
+          if (PU::searchBv(pu, cuPelX, cuPelY, iRoiWidth, iRoiHeight, iPicWidth, iPicHeight, xBv, yBv, lcuWidth))
+#else
+          if (searchBv(pu, cuPelX, cuPelY, iRoiWidth, iRoiHeight, iPicWidth, iPicHeight, xBv, yBv, lcuWidth))
+#endif
+          {
+            buffered = true;
+            Distortion sad = m_pcRdCost->getBvCostMultiplePreds(xBv, yBv, pu.cs->sps->getAMVREnabledFlag(), rribcFlipType);
+            cStruct.pcPatternKey = (rribcFlipType == 0) ? pcPatternKey : ((rribcFlipType == 1) ? pcPatternKeyFlipH : pcPatternKeyFlipV);
+            m_pcRdCost->setDistParam(m_cDistParam, *cStruct.pcPatternKey, cStruct.piRefY, cStruct.iRefStride, m_lumaClpRng.bd, COMPONENT_Y, cStruct.subShiftMode);
+            m_cDistParam.cur.buf = cStruct.piRefY + cStruct.iRefStride * yBv + xBv;
+            sad += m_cDistParam.distFunc(m_cDistParam);
+            if (!isCalc[rribcFlipType])
+            {
+              cand0Cost[rribcFlipType] = sad;
+              isCalc[rribcFlipType]    = true;
+            }
+            if (sad < ruiCost)
+            {
+              rcMv                 = bv;
+              ruiCost              = sad;
+              pu.cu->rribcFlipType = rribcFlipType;
+            }
+            else if (sad == ruiCost)
+            {
+              // stabilise the search through the unordered list
+              if (abs(bv.hor) < abs(rcMv.getHor()) || (bv.hor == rcMv.getHor() && abs(bv.ver) < abs(rcMv.getVer())))
+              {
+                // update the vector.
+                rcMv                 = bv;
+                pu.cu->rribcFlipType = rribcFlipType;
+              }
+            }
+          }
+        }
+      }
+
+      if (buffered)
+      {
+        Mv  cMvPredEncOnly[IBC_NUM_CANDIDATES];
+        int nbPreds = 0;
+        PU::getIbcMVPsEncOnly(pu, cMvPredEncOnly, nbPreds);
+
+        for (unsigned int cand = 0; cand < nbPreds; cand++)
+        {
+          int xPred = cMvPredEncOnly[cand].getHor();
+          int yPred = cMvPredEncOnly[cand].getVer();
+
+          for (int rribcFlipType = 0; rribcFlipType < numRribcType; rribcFlipType++)
+          {
+            if (isSkip[rribcFlipType])
+            {
+              continue;
+            }
+            if ((rribcFlipType == 1 && yPred != 0) || (rribcFlipType == 2 && xPred != 0))
+            {
+              continue;
+            }
+#if JVET_Z0084_IBC_TM
+            if (PU::searchBv(pu, cuPelX, cuPelY, iRoiWidth, iRoiHeight, iPicWidth, iPicHeight, xPred, yPred, lcuWidth))
+#else
+            if (searchBv(pu, cuPelX, cuPelY, iRoiWidth, iRoiHeight, iPicWidth, iPicHeight, xPred, yPred, lcuWidth))
+#endif
+            {
+              Distortion sad = m_pcRdCost->getBvCostMultiplePreds(xPred, yPred, pu.cs->sps->getAMVREnabledFlag(), rribcFlipType);
+              cStruct.pcPatternKey = (rribcFlipType == 0) ? pcPatternKey : ((rribcFlipType == 1) ? pcPatternKeyFlipH : pcPatternKeyFlipV);
+              m_pcRdCost->setDistParam(m_cDistParam, *cStruct.pcPatternKey, cStruct.piRefY, cStruct.iRefStride, m_lumaClpRng.bd, COMPONENT_Y, cStruct.subShiftMode);
+              m_cDistParam.cur.buf = cStruct.piRefY + cStruct.iRefStride * yPred + xPred;
+              sad += m_cDistParam.distFunc(m_cDistParam);
+              if (sad >= minCostProj)
+              {
+                continue;
+              }
+              if (sad < ruiCost)
+              {
+                rcMv.set(xPred, yPred);
+                ruiCost              = sad;
+                pu.cu->rribcFlipType = rribcFlipType;
+              }
+              else if (sad == ruiCost)
+              {
+                // stabilise the search through the unordered list
+                if (abs(xPred) < abs(rcMv.getHor()) || (xPred == rcMv.getHor() && abs(yPred) < abs(rcMv.getVer())))
+                {
+                  // update the vector.
+                  rcMv.set(xPred, yPred);
+                  pu.cu->rribcFlipType = rribcFlipType;
+                }
+              }
+
+              m_ctuRecord[pu.lumaPos()][pu.lumaSize()].bvRecord[Mv(xPred, yPred)] = sad;
+            }
+          }
+        }
+      }
+    }
+  }
+  else if (m_pcEncCfg->getIBCFastMethod() & IBC_FAST_METHOD_BUFFERBV)
+#else
   if (m_pcEncCfg->getIBCFastMethod() & IBC_FAST_METHOD_BUFFERBV)
+#endif
   {
     ruiCost = MAX_UINT;
     std::unordered_map<Mv, Distortion>& history = m_ctuRecord[pu.lumaPos()][pu.lumaSize()].bvRecord;
+#if TEST_3_2
+    std::vector<std::pair<Mv, Distortion>> historyOrdered(history.size());
+    int                                    i = 0;
+    for (std::unordered_map<Mv, Distortion>::iterator p = history.begin(); p != history.end(); p++)
+    {
+      historyOrdered[i] = { p->first, p->second };
+      i++;
+    }
+    std::stable_sort(historyOrdered.begin(), historyOrdered.end(),[](const std::pair<Mv, Distortion> &l, const std::pair<Mv, Distortion> &r)
+                     { return (l.second < r.second) || (l.second == r.second && (l.first.getHor() < r.first.getHor() || (l.first.getHor() == r.first.getHor() && l.first.getVer() < r.first.getVer()))); });
+
+    for (int i = 0; i < history.size(); i++)
+    {
+        const Mv &bv  = historyOrdered[i].first;
+#else
     for (std::unordered_map<Mv, Distortion>::iterator p = history.begin(); p != history.end(); p++)
     {
       const Mv& bv = p->first;
+#endif
 
       int xBv = bv.hor;
       int yBv = bv.ver;
@@ -1484,26 +1881,53 @@ void InterSearch::xIBCEstimation(PredictionUnit& pu, PelUnitBuf& origBuf,
       if (searchBv(pu, cuPelX, cuPelY, iRoiWidth, iRoiHeight, iPicWidth, iPicHeight, xBv, yBv, lcuWidth))
 #endif
       {
+#if TEST_3_2
+        for (int rribcFlipType = 0; rribcFlipType < numRribcType; rribcFlipType++)
+        {
+          if ((rribcFlipType == 1 && yBv != 0) || (rribcFlipType == 2 && xBv != 0))
+          {
+            continue;
+          }
+          buffered = true;
+          Distortion sad = m_pcRdCost->getBvCostMultiplePreds(xBv, yBv, pu.cs->sps->getAMVREnabledFlag(), rribcFlipType);
+          cStruct.pcPatternKey = (rribcFlipType == 0) ? pcPatternKey : ((rribcFlipType == 1) ? pcPatternKeyFlipH : pcPatternKeyFlipV);
+          m_pcRdCost->setDistParam(m_cDistParam, *cStruct.pcPatternKey, cStruct.piRefY, cStruct.iRefStride, m_lumaClpRng.bd, COMPONENT_Y, cStruct.subShiftMode);
+#else
         buffered = true;
         Distortion sad = m_pcRdCost->getBvCostMultiplePreds(xBv, yBv, pu.cs->sps->getAMVREnabledFlag());
+#endif
         m_cDistParam.cur.buf = cStruct.piRefY + cStruct.iRefStride * yBv + xBv;
         sad += m_cDistParam.distFunc(m_cDistParam);
         if (sad < ruiCost)
         {
           rcMv = bv;
           ruiCost = sad;
+#if TEST_3_2
+          pu.cu->rribcFlipType = rribcFlipType;
+#endif
         }
         else if (sad == ruiCost)
         {
           // stabilise the search through the unordered list
-          if (bv.hor < rcMv.getHor()
-            || (bv.hor == rcMv.getHor() && bv.ver < rcMv.getVer()))
+#if TEST_3_2
+          if (abs(bv.hor) < abs(rcMv.getHor()) || (bv.hor == rcMv.getHor() && abs(bv.ver) < abs(rcMv.getVer())))
+          {
+            // update the vector.
+            rcMv                 = bv;
+            pu.cu->rribcFlipType = rribcFlipType;
+          }
+        }
+        }
+      }
+#else
+          if (bv.hor < rcMv.getHor() || (bv.hor == rcMv.getHor() && bv.ver < rcMv.getVer()))
           {
             // update the vector.
             rcMv = bv;
           }
         }
       }
+#endif
     }
 
     if (buffered)
@@ -1523,26 +1947,46 @@ void InterSearch::xIBCEstimation(PredictionUnit& pu, PelUnitBuf& origBuf,
         if (searchBv(pu, cuPelX, cuPelY, iRoiWidth, iRoiHeight, iPicWidth, iPicHeight, xPred, yPred, lcuWidth))
 #endif
         {
+#if TEST_3_2
+          for (int rribcFlipType = 0; rribcFlipType < numRribcType; rribcFlipType++)
+          {
+            if ((rribcFlipType == 1 && yPred != 0) || (rribcFlipType == 2 && xPred != 0))
+            {
+              continue;
+            }
+            Distortion sad = m_pcRdCost->getBvCostMultiplePreds(xPred, yPred, pu.cs->sps->getAMVREnabledFlag(), rribcFlipType);
+            cStruct.pcPatternKey = (rribcFlipType == 0) ? pcPatternKey : ((rribcFlipType == 1) ? pcPatternKeyFlipH : pcPatternKeyFlipV);
+            m_pcRdCost->setDistParam(m_cDistParam, *cStruct.pcPatternKey, cStruct.piRefY, cStruct.iRefStride, m_lumaClpRng.bd, COMPONENT_Y, cStruct.subShiftMode);
+#else
           Distortion sad = m_pcRdCost->getBvCostMultiplePreds(xPred, yPred, pu.cs->sps->getAMVREnabledFlag());
+#endif
           m_cDistParam.cur.buf = cStruct.piRefY + cStruct.iRefStride * yPred + xPred;
           sad += m_cDistParam.distFunc(m_cDistParam);
           if (sad < ruiCost)
           {
             rcMv.set(xPred, yPred);
             ruiCost = sad;
+#if TEST_3_2
+            pu.cu->rribcFlipType = rribcFlipType;
+#endif
           }
           else if (sad == ruiCost)
           {
             // stabilise the search through the unordered list
-            if (xPred < rcMv.getHor()
-              || (xPred == rcMv.getHor() && yPred < rcMv.getVer()))
+            if (xPred < rcMv.getHor() || (xPred == rcMv.getHor() && yPred < rcMv.getVer()))
             {
               // update the vector.
               rcMv.set(xPred, yPred);
+#if TEST_3_2
+              pu.cu->rribcFlipType = rribcFlipType;
+#endif
             }
           }
 
           m_ctuRecord[pu.lumaPos()][pu.lumaSize()].bvRecord[Mv(xPred, yPred)] = sad;
+#if TEST_3_2
+          }
+#endif
         }
       }
     }
@@ -1557,8 +2001,32 @@ void InterSearch::xIBCEstimation(PredictionUnit& pu, PelUnitBuf& origBuf,
     xSetIntraSearchRange(pu, pu.lwidth(), pu.lheight(), localSearchRangeX, localSearchRangeY, cMvSrchRngLT, cMvSrchRngRB);
 
     //  Do integer search
+#if TEST_3_2
+    Distortion minCost = MAX_UINT;
+    Mv         tempMv;
+    tempMv.setZero();
+    for (int rribcFlipType = 0; rribcFlipType < numRribcType; rribcFlipType++)
+    {
+      cStruct.pcPatternKey = (rribcFlipType == 0) ? pcPatternKey : ((rribcFlipType == 1) ? pcPatternKeyFlipH : pcPatternKeyFlipV);
+      m_pcRdCost->setDistParam(m_cDistParam, *cStruct.pcPatternKey, cStruct.piRefY, cStruct.iRefStride, m_lumaClpRng.bd, COMPONENT_Y, cStruct.subShiftMode);
+      xIntraPatternSearch(pu, cStruct, tempMv, ruiCost, &cMvSrchRngLT, &cMvSrchRngRB, pcMvPred[rribcFlipType], rribcFlipType);
+      if (ruiCost < minCost)
+      {
+        minCost = ruiCost;
+        rcMv.set(tempMv.getHor(), tempMv.getVer());
+        pu.cu->rribcFlipType = rribcFlipType;
+      }
+    }
+  }
+  if (numRribcType > 1)
+  {
+    m_tmpStorageCUflipH.destroy();
+    m_tmpStorageCUflipV.destroy();
+  }
+#else
     xIntraPatternSearch(pu, cStruct, rcMv, ruiCost, &cMvSrchRngLT, &cMvSrchRngRB, pcMvPred);
   }
+#endif
 }
 
 // based on xSetSearchRange
@@ -1614,7 +2082,11 @@ void InterSearch::xSetIntraSearchRange(PredictionUnit& pu, int iRoiWidth, int iR
   rcMvSrchRngRB >>= 2;
 }
 
+#if TEST_3_2
+bool InterSearch::predIBCSearch( CodingUnit& cu, Partitioner& partitioner, const int localSearchRangeX, const int localSearchRangeY, IbcHashMap& ibcHashMap, bool isSecondPass)
+#else
 bool InterSearch::predIBCSearch(CodingUnit& cu, Partitioner& partitioner, const int localSearchRangeX, const int localSearchRangeY, IbcHashMap& ibcHashMap)
+#endif
 {
   Mv           cMvSrchRngLT;
   Mv           cMvSrchRngRB;
@@ -1625,12 +2097,66 @@ bool InterSearch::predIBCSearch(CodingUnit& cu, Partitioner& partitioner, const
 #if JVET_Z0131_IBC_BVD_BINARIZATION
   xEstBvdBitCosts(m_pcRdCost->getBvdBitCosts());
 #endif
+#if TEST_3_2
+  CodedCUInfo& relatedCU = ((EncModeCtrlMTnoRQT *)m_modeCtrl)->getBlkInfo(partitioner.currArea());
+#endif
 
   for (auto &pu : CU::traversePUs(cu))
   {
     m_maxCompIDToPred = MAX_NUM_COMPONENT;
 
     CHECK(pu.cu != &cu, "PU is contained in another CU");
+#if TEST_3_2
+    int numRribcType = 3;
+    if (isSecondPass)
+    {
+      if (!relatedCU.isRribcCoded)
+      {
+        numRribcType = 1;
+      }
+    }
+    Mv       cMv;
+    cMv.setZero();
+    int iBvpNum    = 2;
+    int bvpIdxBest = 0;
+    Distortion cost = 0;
+
+    AMVPInfo amvpInfo4Pel[3];
+    AMVPInfo amvpInfo[3];
+    Mv       cMvPred[3][2];
+    for (int i = 0; i < numRribcType; i++)
+    {
+      pu.cu->rribcFlipType = i;
+
+      // prepare imv = 2 accuracy predictor info
+      pu.cu->imv      = 2;
+#if JVET_Z0084_IBC_TM && TM_AMVP
+      PU::fillIBCMvpCand(pu, amvpInfo4Pel[i], this);
+#else
+      PU::fillIBCMvpCand(pu, amvpInfo4Pel[i]);
+#endif
+
+      // prepare imv = 0 accuracy predictor info
+      pu.cu->imv = 0;
+#if JVET_Z0084_IBC_TM && TM_AMVP
+      PU::fillIBCMvpCand(pu, amvpInfo[i], this);
+#else
+      PU::fillIBCMvpCand(pu, amvpInfo[i]);
+#endif
+
+      // store in full pel accuracy, shift before use in search
+      cMvPred[i][0] = amvpInfo[i].mvCand[0];
+      cMvPred[i][0].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT);
+      cMvPred[i][1] = amvpInfo[i].mvCand[1];
+      cMvPred[i][1].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT);
+      if (pu.cs->sps->getMaxNumIBCMergeCand() == 1)
+      {
+        iBvpNum    = 1;
+        cMvPred[i][1] = cMvPred[i][0];
+      }
+    }
+    pu.cu->rribcFlipType = 0;
+#else
     //////////////////////////////////////////////////////////
     /// ibc search
     pu.cu->imv = 2;
@@ -1665,17 +2191,26 @@ bool InterSearch::predIBCSearch(CodingUnit& cu, Partitioner& partitioner, const
       iBvpNum = 1;
       cMvPred[1] = cMvPred[0];
     }
+#endif
 
     if (m_pcEncCfg->getIBCHashSearch())
     {
+#if TEST_3_2
+      xxIBCHashSearch(pu, cMvPred, iBvpNum, cMv, bvpIdxBest, ibcHashMap, amvpInfo4Pel, numRribcType);
+#else
       xxIBCHashSearch(pu, cMvPred, iBvpNum, cMv, bvpIdxBest, ibcHashMap);
+#endif
     }
 
     if (cMv.getHor() == 0 && cMv.getVer() == 0)
     {
       // if hash search does not work or is not enabled
       PelUnitBuf origBuf = pu.cs->getOrgBuf(pu);
+#if TEST_3_2
+      xIBCEstimation(pu, origBuf, cMvPred, cMv, cost, localSearchRangeX, localSearchRangeY, numRribcType);
+#else
       xIBCEstimation(pu, origBuf, cMvPred, cMv, cost, localSearchRangeX, localSearchRangeY);
+#endif
     }
 
     if (cMv.getHor() == 0 && cMv.getVer() == 0)
@@ -1687,7 +2222,9 @@ bool InterSearch::predIBCSearch(CodingUnit& cu, Partitioner& partitioner, const
 #if JVET_Z0131_IBC_BVD_BINARIZATION
     m_pcRdCost->setPredictors(cMvPred);
     m_pcRdCost->setCostScale(0);
-#if JVET_Z0084_IBC_TM
+#if TEST_3_2
+    m_pcRdCost->getBvCostMultiplePreds(cMv.getHor(), cMv.getVer(), pu.cs->sps->getAMVREnabledFlag(), pu.cu->rribcFlipType, &pu.cu->imv, &bvpIdxBest, true, &amvpInfo4Pel[pu.cu->rribcFlipType]);
+#elif JVET_Z0084_IBC_TM
     m_pcRdCost->getBvCostMultiplePreds(cMv.getHor(), cMv.getVer(), pu.cs->sps->getAMVREnabledFlag(), &pu.cu->imv, &bvpIdxBest, true, &amvpInfo4Pel);
 #else
     m_pcRdCost->getBvCostMultiplePreds(cMv.getHor(), cMv.getVer(), pu.cs->sps->getAMVREnabledFlag(), &pu.cu->imv, &bvpIdxBest);
@@ -1699,16 +2236,31 @@ bool InterSearch::predIBCSearch(CodingUnit& cu, Partitioner& partitioner, const
 
     for (int bvpIdxTemp = 0; bvpIdxTemp<iBvpNum; bvpIdxTemp++)
     {
+#if TEST_3_2
+      Mv ccMvPred = cMvPred[pu.cu->rribcFlipType][bvpIdxTemp];
+      m_pcRdCost->setPredictor(ccMvPred);
+      bitsBVPTemp = m_pcRdCost->getBitsOfVectorWithPredictor(cMv.getHor(), cMv.getVer(), 0, cu.rribcFlipType);
+#else
       m_pcRdCost->setPredictor(cMvPred[bvpIdxTemp]);
 
       bitsBVPTemp = m_pcRdCost->getBitsOfVectorWithPredictor(cMv.getHor(), cMv.getVer(), 0);
+#endif
 
       if (bitsBVPTemp < bitsBVPBest)
       {
         bitsBVPBest = bitsBVPTemp;
         bvpIdxBest = bvpIdxTemp;
 
+#if TEST_3_2
+        bool diffMV = false;
+        if ((pu.cu->rribcFlipType == 1 && cMv.getHor() != ccMvPred.getHor()) || (pu.cu->rribcFlipType == 2 && cMv.getVer() != ccMvPred.getVer()) || (pu.cu->rribcFlipType == 0 && cMv != ccMvPred))
+        {
+          diffMV = true;
+        }
+        if (cu.cs->sps->getAMVREnabledFlag() && diffMV)
+#else
         if (cu.cs->sps->getAMVREnabledFlag() && cMv != cMvPred[bvpIdxTemp])
+#endif
           pu.cu->imv = 1; // set as full-pel
         else
           pu.cu->imv = 0; // set as fractional-pel
@@ -1721,17 +2273,35 @@ bool InterSearch::predIBCSearch(CodingUnit& cu, Partitioner& partitioner, const
       Mv mvPredQuadPel;
       if ((cMv.getHor() % 4 == 0) && (cMv.getVer() % 4 == 0) && (pu.cs->sps->getAMVREnabledFlag()))
       {
+#if TEST_3_2
+        mvPredQuadPel = amvpInfo4Pel[pu.cu->rribcFlipType].mvCand[bvpIdxTemp];
+#else
         mvPredQuadPel = amvpInfo4Pel.mvCand[bvpIdxTemp];// cMvPred[bvpIdxTemp];
 
+#endif
+
         mvPredQuadPel.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_4PEL);
 
         m_pcRdCost->setPredictor(mvPredQuadPel);
 
+#if TEST_3_2
+        bitsBVPQP = m_pcRdCost->getBitsOfVectorWithPredictor(cMv.getHor() >> 2, cMv.getVer() >> 2, 0, cu.rribcFlipType);
+#else
         bitsBVPQP = m_pcRdCost->getBitsOfVectorWithPredictor(cMv.getHor() >> 2, cMv.getVer() >> 2, 0);
+#endif
 
       }
       mvPredQuadPel.changePrecision(MV_PRECISION_4PEL, MV_PRECISION_INT);
+#if TEST_3_2
+      bool diffMV = false;
+      if ((pu.cu->rribcFlipType == 1 && cMv.getHor() != mvPredQuadPel.getHor()) || (pu.cu->rribcFlipType == 2 && cMv.getVer() != mvPredQuadPel.getVer()) || (pu.cu->rribcFlipType == 0 && cMv != mvPredQuadPel))
+      {
+        diffMV = true;
+      }
+      if ((bitsBVPQP < bitsBVPBest) && diffMV)
+#else
       if (bitsBVPQP < bitsBVPBest && cMv != mvPredQuadPel)
+#endif
       {
         bitsBVPBest = bitsBVPQP;
         bvpIdxBest = bvpIdxTemp;
@@ -1743,16 +2313,36 @@ bool InterSearch::predIBCSearch(CodingUnit& cu, Partitioner& partitioner, const
     }
 #endif
 
+
     pu.bv = cMv; // bv is always at integer accuracy
     cMv.changePrecision(MV_PRECISION_INT, MV_PRECISION_INTERNAL);
     pu.mv[REF_PIC_LIST_0] = cMv; // store in fractional pel accuracy
 
     pu.mvpIdx[REF_PIC_LIST_0] = bvpIdxBest;
 
-    if(pu.cu->imv == 2 && cMv != amvpInfo4Pel.mvCand[bvpIdxBest])
+#if TEST_3_2
+    if (pu.cu->imv == 2 && cMv != amvpInfo4Pel[pu.cu->rribcFlipType].mvCand[bvpIdxBest])
+    {
+      pu.mvd[REF_PIC_LIST_0] = cMv - amvpInfo4Pel[pu.cu->rribcFlipType].mvCand[bvpIdxBest];
+    }
+    else
+    {
+      pu.mvd[REF_PIC_LIST_0] = cMv - amvpInfo[pu.cu->rribcFlipType].mvCand[bvpIdxBest];
+    }
+    if (pu.cu->rribcFlipType == 1)
+    {
+      pu.mvd[REF_PIC_LIST_0].setVer(0);
+    }
+    else if (pu.cu->rribcFlipType == 2)
+    {
+      pu.mvd[REF_PIC_LIST_0].setHor(0);
+    }
+#else
+    if (pu.cu->imv == 2 && cMv != amvpInfo4Pel.mvCand[bvpIdxBest])
       pu.mvd[REF_PIC_LIST_0] = cMv - amvpInfo4Pel.mvCand[bvpIdxBest];
     else
       pu.mvd[REF_PIC_LIST_0] = cMv - amvpInfo.mvCand[bvpIdxBest];
+#endif
 
     if (pu.mvd[REF_PIC_LIST_0] == Mv(0, 0))
       pu.cu->imv = 0;
@@ -1768,11 +2358,61 @@ bool InterSearch::predIBCSearch(CodingUnit& cu, Partitioner& partitioner, const
   return true;
 }
 
-void InterSearch::xxIBCHashSearch(PredictionUnit& pu, Mv* mvPred, int numMvPred, Mv &mv, int& idxMvPred, IbcHashMap& ibcHashMap)
+#if TEST_3_2
+void InterSearch::xxIBCHashSearch(PredictionUnit &pu, Mv mvPred[3][2], int numMvPred, Mv &mv, int &idxMvPred, IbcHashMap &ibcHashMap, AMVPInfo amvpInfo4Pel[3], int numRribcType)
+#else
+void InterSearch::xxIBCHashSearch(PredictionUnit &pu, Mv *mvPred, int numMvPred, Mv &mv, int &idxMvPred, IbcHashMap &ibcHashMap)
+#endif
 {
   mv.setZero();
   m_pcRdCost->setCostScale(0);
 
+#if TEST_3_2
+  const unsigned int lcuWidth  = pu.cs->slice->getSPS()->getMaxCUWidth();
+  const int          cuPelX    = pu.Y().x;
+  const int          cuPelY    = pu.Y().y;
+  const int          picWidth  = pu.cs->slice->getPPS()->getPicWidthInLumaSamples();
+  const int          picHeight = pu.cs->slice->getPPS()->getPicHeightInLumaSamples();
+  int                roiWidth  = pu.lwidth();
+  int                roiHeight = pu.lheight();
+#if JVET_Z0131_IBC_BVD_BINARIZATION
+  Distortion minCost = MAX_UINT64;
+  m_pcRdCost->setPredictors(mvPred);
+#else
+  unsigned int minCost = MAX_UINT;
+#endif
+
+  std::vector<Position> candPos[3];
+  bool                  isHashMatch[3] = { false };
+  for (int rribcFlipType = 0; rribcFlipType < numRribcType; rribcFlipType++)
+  {
+    if(rribcFlipType && m_pcEncCfg->getIntraPeriod() <= 1)
+    {
+      Distortion TH = m_pcEncCfg->getIntraPeriod() == -1 ? 50 : 200;
+      if ((minCost < TH) || (!isHashMatch[rribcFlipType - 1]))
+      {
+        continue;
+      }
+    }
+    else if (rribcFlipType)
+    {
+      if (minCost < 100 || (rribcFlipType == 1 && !isHashMatch[0]) || (rribcFlipType == 2 && !isHashMatch[0] && !isHashMatch[1]))
+      {
+        continue;
+      }
+    }
+    isHashMatch[rribcFlipType] = ibcHashMap.ibcHashMatch(pu, pu.Y(), candPos[rribcFlipType], *pu.cs, m_pcEncCfg->getIBCHashSearchMaxCand(), m_pcEncCfg->getIBCHashSearchRange4SmallBlk(), rribcFlipType);
+    if (!isHashMatch[rribcFlipType])
+    {
+      continue;
+    }
+    for (std::vector<Position>::iterator pos = candPos[rribcFlipType].begin(); pos != candPos[rribcFlipType].end(); pos++)
+    {
+      if ((rribcFlipType == 1 && (*pos - pu.Y().pos()).y != 0) || (rribcFlipType == 2 && (*pos - pu.Y().pos()).x != 0))
+      {
+        continue;
+      }
+#else
   std::vector<Position> candPos;
   if (ibcHashMap.ibcHashMatch(pu.Y(), candPos, *pu.cs, m_pcEncCfg->getIBCHashSearchMaxCand(), m_pcEncCfg->getIBCHashSearchRange4SmallBlk()))
   {
@@ -1793,6 +2433,7 @@ void InterSearch::xxIBCHashSearch(PredictionUnit& pu, Mv* mvPred, int numMvPred,
 
     for (std::vector<Position>::iterator pos = candPos.begin(); pos != candPos.end(); pos++)
     {
+#endif
       Position bottomRight = pos->offset(pu.Y().width - 1, pu.Y().height - 1);
       if (pu.cs->isDecomp(*pos, CHANNEL_TYPE_LUMA) && pu.cs->isDecomp(bottomRight, CHANNEL_TYPE_LUMA))
       {
@@ -1809,25 +2450,40 @@ void InterSearch::xxIBCHashSearch(PredictionUnit& pu, Mv* mvPred, int numMvPred,
           continue;
         }
 
+
 #if JVET_Z0131_IBC_BVD_BINARIZATION
+#if TEST_3_2
+        Distortion cost = m_pcRdCost->getBvCostMultiplePreds(candMv.getHor(), candMv.getVer(), pu.cs->sps->getAMVREnabledFlag(), rribcFlipType, &pu.cu->imv, &idxMvPred, true, &amvpInfo4Pel[rribcFlipType]);
+#else
         Distortion cost = m_pcRdCost->getBvCostMultiplePreds(candMv.getHor(), candMv.getVer(), pu.cs->sps->getAMVREnabledFlag());
+#endif
         if (cost < minCost)
         {
           mv = candMv;
           minCost = cost;
+#if TEST_3_2
+          pu.cu->rribcFlipType = rribcFlipType;
+#endif
         }
 #else
         for (int n = 0; n < numMvPred; n++)
         {
+#if TEST_3_2
+          m_pcRdCost->setPredictor(mvPred[rribcFlipType][n]);
+          unsigned int cost = m_pcRdCost->getBitsOfVectorWithPredictor(candMv.getHor(), candMv.getVer(), 0, rribcFlipType);
+#else
           m_pcRdCost->setPredictor(mvPred[n]);
-
           unsigned int cost = m_pcRdCost->getBitsOfVectorWithPredictor(candMv.getHor(), candMv.getVer(), 0);
+#endif
 
           if (cost < minCost)
           {
             mv = candMv;
             idxMvPred = n;
             minCost = cost;
+#if TEST_3_2
+            pu.cu->rribcFlipType = rribcFlipType;
+#endif
           }
 
           int costQuadPel = MAX_UINT;
@@ -1837,13 +2493,22 @@ void InterSearch::xxIBCHashSearch(PredictionUnit& pu, Mv* mvPred, int numMvPred,
             int imvShift = 2;
             int offset = 1 << (imvShift - 1);
 
+#if TEST_3_2
+            int x = (mvPred[rribcFlipType][n].hor + offset - (mvPred[rribcFlipType][n].hor >= 0)) >> 2;
+            int y = (mvPred[rribcFlipType][n].ver + offset - (mvPred[rribcFlipType][n].ver >= 0)) >> 2;
+#else
             int x = (mvPred[n].hor + offset - (mvPred[n].hor >= 0)) >> 2;
             int y = (mvPred[n].ver + offset - (mvPred[n].ver >= 0)) >> 2;
+#endif
             mvPredQuadPel.set(x, y);
 
             m_pcRdCost->setPredictor(mvPredQuadPel);
 
+#if TEST_3_2
+            costQuadPel = m_pcRdCost->getBitsOfVectorWithPredictor(candMv.getHor() >> 2, candMv.getVer() >> 2, 0, rribcFlipType);
+#else
             costQuadPel = m_pcRdCost->getBitsOfVectorWithPredictor(candMv.getHor() >> 2, candMv.getVer() >> 2, 0);
+#endif
 
           }
           if (costQuadPel < minCost)
@@ -1851,6 +2516,9 @@ void InterSearch::xxIBCHashSearch(PredictionUnit& pu, Mv* mvPred, int numMvPred,
             mv = candMv;
             idxMvPred = n;
             minCost = costQuadPel;
+#if TEST_3_2
+            pu.cu->rribcFlipType = rribcFlipType;
+#endif
           }
 
         }
@@ -1858,7 +2526,6 @@ void InterSearch::xxIBCHashSearch(PredictionUnit& pu, Mv* mvPred, int numMvPred,
       }
     }
   }
-
 }
 
 
@@ -9782,6 +10449,14 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa
     else
     {
       cs.getRecoBuf().copyFrom( cs.getPredBuf() );
+#if TEST_3_2
+      if (CU::isIBC(cu) && cu.rribcFlipType)
+      {
+        cs.getRecoBuf().Y().flipSignal(cu.rribcFlipType == 1);
+        cs.getRecoBuf().Cb().flipSignal(cu.rribcFlipType == 1);
+        cs.getRecoBuf().Cr().flipSignal(cu.rribcFlipType == 1);
+      }
+#endif
     }
 
     // add empty TU(s)
@@ -9850,19 +10525,65 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa
       }
       else
       {
+#if TEST_3_2
+        if (CU::isIBC(cu) && cu.rribcFlipType)
+        {
+          PelBuf   tmpPattern;
+          CompArea tmpArea(COMPONENT_Y, cu.chromaFormat, Position(0, 0), Size(cs.getOrgBuf(COMPONENT_Y).width, cs.getOrgBuf(COMPONENT_Y).height));
+          tmpPattern = m_tmpStorageLCU.getBuf(tmpArea);
+          tmpPattern.copyFrom(cs.getOrgBuf(COMPONENT_Y));
+          tmpPattern.flipSignal(cu.rribcFlipType == 1);
+          cs.getResiBuf(COMPONENT_Y).rspSignalAndSubtract(tmpPattern, cs.getPredBuf(COMPONENT_Y), m_pcReshape->getFwdLUT());
+        }
+        else
+#endif
         cs.getResiBuf( COMPONENT_Y ).rspSignalAndSubtract( cs.getOrgBuf( COMPONENT_Y ), cs.getPredBuf( COMPONENT_Y ), m_pcReshape->getFwdLUT() );
       }
     }
     else
     {
+#if TEST_3_2
+      if (CU::isIBC(cu) && cu.rribcFlipType)
+      {
+        PelBuf   tmpPattern;
+        CompArea tmpArea(COMPONENT_Y, cu.chromaFormat, Position(0, 0), Size(cs.getOrgBuf(COMPONENT_Y).width, cs.getOrgBuf(COMPONENT_Y).height));
+        tmpPattern = m_tmpStorageLCU.getBuf(tmpArea);
+        tmpPattern.copyFrom(cs.getOrgBuf(COMPONENT_Y));
+        tmpPattern.flipSignal(cu.rribcFlipType == 1);
+        cs.getResiBuf(COMPONENT_Y).subtract(tmpPattern, cs.getPredBuf(COMPONENT_Y));
+      }
+      else
+#endif
       cs.getResiBuf( COMPONENT_Y ).subtract( cs.getOrgBuf( COMPONENT_Y ), cs.getPredBuf( COMPONENT_Y ) );
     }
   }
 
   if( chroma && isChromaEnabled( cs.pcv->chrFormat ) )
   {
+#if TEST_3_2
+    if (CU::isIBC(cu) && cu.rribcFlipType)
+    {
+      PelBuf   tmpPattern;
+      CompArea tmpArea1(COMPONENT_Cb, cu.chromaFormat, Position(0, 0), Size(cs.getOrgBuf(COMPONENT_Cb).width, cs.getOrgBuf(COMPONENT_Cb).height));
+      tmpPattern = m_tmpStorageLCU.getBuf(tmpArea1);
+      tmpPattern.copyFrom(cs.getOrgBuf(COMPONENT_Cb));
+      tmpPattern.flipSignal(cu.rribcFlipType == 1);
+      cs.getResiBuf(COMPONENT_Cb).subtract(tmpPattern, cs.getPredBuf(COMPONENT_Cb));
+
+      CompArea tmpArea2(COMPONENT_Cr, cu.chromaFormat, Position(0, 0), Size(cs.getOrgBuf(COMPONENT_Cr).width, cs.getOrgBuf(COMPONENT_Cr).height));
+      tmpPattern = m_tmpStorageLCU.getBuf(tmpArea2);
+      tmpPattern.copyFrom(cs.getOrgBuf(COMPONENT_Cr));
+      tmpPattern.flipSignal(cu.rribcFlipType == 1);
+      cs.getResiBuf(COMPONENT_Cr).subtract(tmpPattern, cs.getPredBuf(COMPONENT_Cr));
+    }
+    else
+    {
+#endif
     cs.getResiBuf( COMPONENT_Cb ).subtract( cs.getOrgBuf( COMPONENT_Cb ), cs.getPredBuf( COMPONENT_Cb ) );
     cs.getResiBuf( COMPONENT_Cr ).subtract( cs.getOrgBuf( COMPONENT_Cr ), cs.getPredBuf( COMPONENT_Cr ) );
+#if TEST_3_2
+    }
+#endif
   }
 
   const UnitArea curUnitArea = partitioner.currArea();
@@ -10133,7 +10854,14 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa
       }
       else
       {
-        cs.getRecoBuf( COMPONENT_Y ).reconstruct( cs.getPredBuf( COMPONENT_Y ), cs.getResiBuf( COMPONENT_Y ), cs.slice->clpRng( COMPONENT_Y ) );
+        cs.getRecoBuf(COMPONENT_Y)
+          .reconstruct(cs.getPredBuf(COMPONENT_Y), cs.getResiBuf(COMPONENT_Y), cs.slice->clpRng(COMPONENT_Y));
+#if TEST_3_2
+        if (CU::isIBC(cu) && cu.rribcFlipType)
+        {
+          cs.getRecoBuf(COMPONENT_Y).flipSignal(cu.rribcFlipType == 1);
+        }
+#endif
       }
     }
     else
@@ -10147,12 +10875,25 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa
       {
         cs.getRecoBuf().bufs[0].rspSignal(m_pcReshape->getFwdLUT());
       }
+#if TEST_3_2
+      if (CU::isIBC(cu) && cu.rribcFlipType)
+      {
+        cs.getRecoBuf().bufs[0].flipSignal(cu.rribcFlipType == 1);
+      }
+#endif
     }
   }
   if (chroma && isChromaEnabled(cs.pcv->chrFormat))
   {
     cs.getRecoBuf().bufs[1].reconstruct(cs.getPredBuf().bufs[1], cs.getResiBuf().bufs[1], cs.slice->clpRngs().comp[1]);
     cs.getRecoBuf().bufs[2].reconstruct(cs.getPredBuf().bufs[2], cs.getResiBuf().bufs[2], cs.slice->clpRngs().comp[2]);
+#if TEST_3_2
+    if (CU::isIBC(cu) && cu.rribcFlipType)
+    {
+      cs.getRecoBuf().bufs[1].flipSignal(cu.rribcFlipType == 1);
+      cs.getRecoBuf().bufs[2].flipSignal(cu.rribcFlipType == 1);
+    }
+#endif
   }
 
   // update with clipped distortion and cost (previously unclipped reconstruction values were used)
diff --git a/source/Lib/EncoderLib/InterSearch.h b/source/Lib/EncoderLib/InterSearch.h
index e0ec55c2..66f17f3c 100644
--- a/source/Lib/EncoderLib/InterSearch.h
+++ b/source/Lib/EncoderLib/InterSearch.h
@@ -121,6 +121,9 @@ struct ModeInfo
 #if JVET_X0049_ADAPT_DMVR
   bool     isBMMrg;
   uint8_t  bmDir;
+#endif
+#if TEST_3_2
+  int rribcFlipType;
 #endif
   bool     isGeo;
   uint8_t     geoSplitDir;
@@ -147,6 +150,9 @@ struct ModeInfo
 #if JVET_X0049_ADAPT_DMVR
     , isBMMrg(false)
     , bmDir(0)
+#endif
+#if TEST_3_2
+    , rribcFlipType(0)
 #endif
   , isGeo(false), geoSplitDir(0), geoMergeIdx0(0), geoMergeIdx1(0)
 #if ENABLE_OBMC
@@ -224,6 +230,9 @@ struct ModeInfo
 #if JVET_X0049_ADAPT_DMVR
     isBMMrg = pu.bmMergeFlag;
     bmDir = pu.bmDir;
+#endif
+#if TEST_3_2
+    rribcFlipType = cu.rribcFlipType;
 #endif
     isGeo = cu.geoFlag;
     geoSplitDir = pu.geoSplitDir;
@@ -314,6 +323,9 @@ private:
   BcwMotionParam  m_uniMotions;
   bool            m_affineModeSelected;
   std::unordered_map< Position, std::unordered_map< Size, BlkRecord> > m_ctuRecord;
+#if TEST_3_2
+  Distortion      minCostProj;
+#endif
   AffineMVInfo       *m_affMVList;
   int             m_affMVListIdx;
   int             m_affMVListSize;
@@ -647,8 +659,13 @@ public:
 
   /// set ME search range
   void setAdaptiveSearchRange       ( int iDir, int iRefIdx, int iSearchRange) { CHECK(iDir >= MAX_NUM_REF_LIST_ADAPT_SR || iRefIdx>=int(MAX_IDX_ADAPT_SR), "Invalid index"); m_aaiAdaptSR[iDir][iRefIdx] = iSearchRange; }
+#if TEST_3_2
+  bool  predIBCSearch           ( CodingUnit& cu, Partitioner& partitioner, const int localSearchRangeX, const int localSearchRangeY, IbcHashMap& ibcHashMap, bool isSecondPass = false );
+  void  xIntraPatternSearch          ( PredictionUnit& pu, IntTZSearchStruct&  cStruct, Mv& rcMv, Distortion&  ruiCost, Mv* cMvSrchRngLT, Mv* cMvSrchRngRB, Mv* pcMvPred, int rribcFlipType );
+#else
   bool  predIBCSearch           ( CodingUnit& cu, Partitioner& partitioner, const int localSearchRangeX, const int localSearchRangeY, IbcHashMap& ibcHashMap);
-  void  xIntraPatternSearch         ( PredictionUnit& pu, IntTZSearchStruct&  cStruct, Mv& rcMv, Distortion&  ruiCost, Mv* cMvSrchRngLT, Mv* cMvSrchRngRB, Mv* pcMvPred);
+  void  xIntraPatternSearch         ( PredictionUnit& pu, IntTZSearchStruct&  cStruct, Mv& rcMv, Distortion&  ruiCost, Mv* cMvSrchRngLT, Mv* cMvSrchRngRB, Mv* pcMvPred );
+#endif
   void  xSetIntraSearchRange        ( PredictionUnit& pu, int iRoiWidth, int iRoiHeight, const int localSearchRangeX, const int localSearchRangeY, Mv& rcMvSrchRngLT, Mv& rcMvSrchRngRB);
   void  resetIbcSearch()
   {
@@ -658,9 +675,15 @@ public:
     }
     m_defaultCachedBvs.currCnt = 0;
   }
+#if TEST_3_2
+  void xIBCEstimation(PredictionUnit &pu, PelUnitBuf &origBuf, Mv pcMvPred[3][2], Mv &rcMv, Distortion &ruiCost, const int localSearchRangeX, const int localSearchRangeY, int numRribcType);
+  void xIBCSearchMVCandUpdate( Distortion uiSad, int x, int y, Distortion *uiSadBestCand, Mv *cMVCand);
+  int  xIBCSearchMVChromaRefine( PredictionUnit &pu, int iRoiWidth, int iRoiHeight, int cuPelX, int cuPelY, Distortion *uiSadBestCand, Mv *cMVCand, int rribcFlipType );
+#else
   void  xIBCEstimation   ( PredictionUnit& pu, PelUnitBuf& origBuf, Mv     *pcMvPred, Mv     &rcMv, Distortion &ruiCost, const int localSearchRangeX, const int localSearchRangeY);
   void  xIBCSearchMVCandUpdate  ( Distortion  uiSad, int x, int y, Distortion* uiSadBestCand, Mv* cMVCand);
-  int   xIBCSearchMVChromaRefine( PredictionUnit& pu, int iRoiWidth, int iRoiHeight, int cuPelX, int cuPelY, Distortion* uiSadBestCand, Mv*     cMVCand);
+  int   xIBCSearchMVChromaRefine( PredictionUnit& pu, int iRoiWidth, int iRoiHeight, int cuPelX, int cuPelY, Distortion* uiSadBestCand, Mv*     cMVCand );
+#endif
   void addToSortList(std::list<BlockHash>& listBlockHash, std::list<int>& listCost, int cost, const BlockHash& blockHash);
   bool predInterHashSearch(CodingUnit& cu, Partitioner& partitioner, bool& isPerfectMatch);
   bool xHashInterEstimation(PredictionUnit& pu, RefPicList& bestRefPicList, int& bestRefIndex, Mv& bestMv, Mv& bestMvd, int& bestMVPIndex, bool& isPerfectMatch);
@@ -978,7 +1001,11 @@ protected:
 
   void  setWpScalingDistParam     ( int iRefIdx, RefPicList eRefPicListCur, Slice *slice );
 private:
+#if TEST_3_2
+  void xxIBCHashSearch(PredictionUnit &pu, Mv mvPred[3][2], int numMvPred, Mv &mv, int &idxMvPred, IbcHashMap &ibcHashMap, AMVPInfo amvpInfo4Pel[3], int numRribcType);
+#else
   void  xxIBCHashSearch(PredictionUnit& pu, Mv* mvPred, int numMvPred, Mv &mv, int& idxMvPred, IbcHashMap& ibcHashMap);
+#endif
 public:
 
   void encodeResAndCalcRdInterCU  (CodingStructure &cs, Partitioner &partitioner, const bool &skipResidual
