[llvm] [RISCV] Handle freeze in vp.merge widening codegen prepare (PR #189346)

Luke Lau via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 30 06:07:18 PDT 2026


================
@@ -130,57 +132,64 @@ bool RISCVCodeGenPrepare::visitAnd(BinaryOperator &BO) {
 // generate a single vmerge.vim:
 //
 // loop:
-//   %phi = phi <vscale x 4 x i8> [ zeroinitializer, %entry ], [ %rec, %loop ]
+//   %phi = phi <vscale x 4 x i8> [zeroinitializer, %entry], [%freeze, %loop]
 //   %cmp = icmp ...
 //   %rec = call <vscale x 4 x i8> @llvm.vp.merge(%cmp, i8 true, %phi, %evl)
-//   %trunc = trunc <vscale x 4 x i8> %rec to <vscale x 4 x i1>
+//   %freeze = freeze <vscale x 4 x i8> %rec
+//   %trunc = trunc <vscale x 4 x i8> %freeze to <vscale x 4 x i1>
 //   ...
 // middle:
-//   %res = call i1 @llvm.vector.reduce.or(<vscale x 4 x i1> %rec)
+//   %res = call i1 @llvm.vector.reduce.or(<vscale x 4 x i1> %trunc)
 //
 // The trunc will normally be sunk outside of the loop, but even if there are
 // users inside the loop it is still profitable.
-bool RISCVCodeGenPrepare::widenVPMerge(IntrinsicInst &II) {
-  if (!II.getType()->getScalarType()->isIntegerTy(1))
+bool RISCVCodeGenPrepare::widenVPMerge(Instruction *Root) {
+  if (!Root->getType()->getScalarType()->isIntegerTy(1))
     return false;
 
   Value *Mask, *True, *PhiV, *EVL;
   using namespace PatternMatch;
-  if (!match(&II,
-             m_Intrinsic<Intrinsic::vp_merge>(m_Value(Mask), m_Value(True),
-                                              m_Value(PhiV), m_Value(EVL))))
+  auto m_VPMerge = m_Intrinsic<Intrinsic::vp_merge>(
+      m_Value(Mask), m_Value(True), m_Value(PhiV), m_Value(EVL));
+  if (!match(Root, m_CombineOr(m_VPMerge, m_Freeze(m_VPMerge))))
     return false;
 
   auto *Phi = dyn_cast<PHINode>(PhiV);
   if (!Phi || !Phi->hasOneUse() || Phi->getNumIncomingValues() != 2 ||
       !match(Phi->getIncomingValue(0), m_Zero()) ||
-      Phi->getIncomingValue(1) != &II)
+      Phi->getIncomingValue(1) != Root)
     return false;
 
   Type *WideTy =
-      VectorType::get(IntegerType::getInt8Ty(II.getContext()),
-                      cast<VectorType>(II.getType())->getElementCount());
+      VectorType::get(IntegerType::getInt8Ty(Root->getContext()),
+                      cast<VectorType>(Root->getType())->getElementCount());
 
   IRBuilder<> Builder(Phi);
   PHINode *WidePhi = Builder.CreatePHI(WideTy, 2);
   WidePhi->addIncoming(ConstantAggregateZero::get(WideTy),
                        Phi->getIncomingBlock(0));
-  Builder.SetInsertPoint(&II);
+  Builder.SetInsertPoint(Root);
   Value *WideTrue = Builder.CreateZExt(True, WideTy);
   Value *WideMerge = Builder.CreateIntrinsic(Intrinsic::vp_merge, {WideTy},
                                              {Mask, WideTrue, WidePhi, EVL});
+  if (isa<FreezeInst>(Root))
+    WideMerge = Builder.CreateFreeze(WideMerge);
   WidePhi->addIncoming(WideMerge, Phi->getIncomingBlock(1));
-  Value *Trunc = Builder.CreateTrunc(WideMerge, II.getType());
+  Value *Trunc = Builder.CreateTrunc(WideMerge, Root->getType());
 
-  II.replaceAllUsesWith(Trunc);
+  Root->replaceAllUsesWith(Trunc);
 
   // Break the cycle and delete the old chain.
   Phi->setIncomingValue(1, Phi->getIncomingValue(0));
-  llvm::RecursivelyDeleteTriviallyDeadInstructions(&II);
+  llvm::RecursivelyDeleteTriviallyDeadInstructions(Root);
 
   return true;
 }
 
+bool RISCVCodeGenPrepare::visitFreezeInst(FreezeInst &I) {
+  return widenVPMerge(&I);
----------------
lukel97 wrote:

Done in 039b68b9a4de, I think it makes the code easier to read anyway

https://github.com/llvm/llvm-project/pull/189346


More information about the llvm-commits mailing list